]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
Merge branch 'devel-stable' into devel
authorRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 6 Jan 2011 22:33:32 +0000 (22:33 +0000)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 6 Jan 2011 22:33:32 +0000 (22:33 +0000)
Conflicts:
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/clock.h

681 files changed:
Documentation/accounting/getdelays.c
Documentation/arm/00-INDEX
Documentation/arm/swp_emulation [new file with mode: 0644]
Documentation/filesystems/Locking
Documentation/kernel-parameters.txt
Documentation/power/runtime_pm.txt
Documentation/scsi/scsi_mid_low_api.txt
Documentation/trace/postprocess/trace-vmscan-postprocess.pl
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/boot/compressed/Makefile
arch/arm/boot/compressed/head-shmobile.S [new file with mode: 0644]
arch/arm/common/Kconfig
arch/arm/common/Makefile
arch/arm/common/dmabounce.c
arch/arm/common/gic.c
arch/arm/common/it8152.c
arch/arm/common/timer-sp.c [moved from arch/arm/plat-versatile/timer-sp.c with 95% similarity]
arch/arm/include/asm/assembler.h
arch/arm/include/asm/cache.h
arch/arm/include/asm/clkdev.h
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/domain.h
arch/arm/include/asm/elf.h
arch/arm/include/asm/entry-macro-multi.S [new file with mode: 0644]
arch/arm/include/asm/futex.h
arch/arm/include/asm/hardirq.h
arch/arm/include/asm/hardware/entry-macro-gic.S [new file with mode: 0644]
arch/arm/include/asm/hardware/gic.h
arch/arm/include/asm/hardware/it8152.h
arch/arm/include/asm/hardware/timer-sp.h [moved from arch/arm/plat-versatile/include/plat/timer-sp.h with 100% similarity]
arch/arm/include/asm/highmem.h
arch/arm/include/asm/io.h
arch/arm/include/asm/kexec.h
arch/arm/include/asm/localtimer.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/mach/irq.h
arch/arm/include/asm/mach/time.h
arch/arm/include/asm/module.h
arch/arm/include/asm/page.h
arch/arm/include/asm/pgalloc.h
arch/arm/include/asm/pgtable.h
arch/arm/include/asm/sched_clock.h [new file with mode: 0644]
arch/arm/include/asm/sizes.h
arch/arm/include/asm/smp.h
arch/arm/include/asm/smp_mpidr.h [deleted file]
arch/arm/include/asm/smp_twd.h
arch/arm/include/asm/system.h
arch/arm/include/asm/traps.h
arch/arm/include/asm/uaccess.h
arch/arm/kernel/Makefile
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/fiq.c
arch/arm/kernel/head.S
arch/arm/kernel/irq.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/module.c
arch/arm/kernel/sched_clock.c [new file with mode: 0644]
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_tlb.c [new file with mode: 0644]
arch/arm/kernel/smp_twd.c
arch/arm/kernel/swp_emulate.c [new file with mode: 0644]
arch/arm/kernel/time.c
arch/arm/kernel/traps.c
arch/arm/kernel/vmlinux.lds.S
arch/arm/lib/getuser.S
arch/arm/lib/putuser.S
arch/arm/lib/uaccess.S
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam926x_time.c
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/clock.c
arch/arm/mach-at91/include/mach/at91_mci.h
arch/arm/mach-at91/include/mach/stamp9g20.h [new file with mode: 0644]
arch/arm/mach-bcmring/clock.c
arch/arm/mach-bcmring/core.c
arch/arm/mach-cns3xxx/Kconfig
arch/arm/mach-cns3xxx/core.c
arch/arm/mach-cns3xxx/core.h
arch/arm/mach-cns3xxx/include/mach/entry-macro.S
arch/arm/mach-davinci/clock.h
arch/arm/mach-davinci/include/mach/io.h
arch/arm/mach-davinci/time.c
arch/arm/mach-ep93xx/clock.c
arch/arm/mach-imx/clock-imx1.c
arch/arm/mach-imx/clock-imx21.c
arch/arm/mach-imx/clock-imx25.c
arch/arm/mach-imx/clock-imx27.c
arch/arm/mach-integrator/Kconfig
arch/arm/mach-integrator/core.c
arch/arm/mach-integrator/impd1.c
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-iop13xx/include/mach/io.h
arch/arm/mach-iop13xx/include/mach/memory.h
arch/arm/mach-iop32x/include/mach/io.h
arch/arm/mach-iop33x/include/mach/io.h
arch/arm/mach-ixp23xx/include/mach/io.h
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-ixp4xx/common.c
arch/arm/mach-ixp4xx/include/mach/io.h
arch/arm/mach-kirkwood/include/mach/io.h
arch/arm/mach-ks8695/Kconfig
arch/arm/mach-ks8695/include/mach/memory.h
arch/arm/mach-lpc32xx/clock.c
arch/arm/mach-lpc32xx/timer.c
arch/arm/mach-mmp/clock.h
arch/arm/mach-mmp/time.c
arch/arm/mach-msm/board-msm8x60.c
arch/arm/mach-msm/include/mach/smp.h
arch/arm/mach-msm/timer.c
arch/arm/mach-mx3/clock-imx31.c
arch/arm/mach-mx3/clock-imx35.c
arch/arm/mach-mx5/clock-mx51-mx53.c
arch/arm/mach-mxc91231/clock.c
arch/arm/mach-netx/time.c
arch/arm/mach-nomadik/clock.c
arch/arm/mach-ns9xxx/time-ns9360.c
arch/arm/mach-nuc93x/clock.h
arch/arm/mach-omap1/clock.c
arch/arm/mach-omap1/time.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/include/mach/entry-macro.S
arch/arm/mach-omap2/include/mach/omap4-common.h
arch/arm/mach-omap2/omap-hotplug.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/timer-gp.c
arch/arm/mach-orion5x/include/mach/io.h
arch/arm/mach-pnx4008/clock.c
arch/arm/mach-pxa/Kconfig
arch/arm/mach-pxa/clock.c
arch/arm/mach-pxa/clock.h
arch/arm/mach-pxa/sleep.S
arch/arm/mach-pxa/time.c
arch/arm/mach-realview/core.c
arch/arm/mach-realview/core.h
arch/arm/mach-realview/hotplug.c
arch/arm/mach-realview/include/mach/entry-macro.S
arch/arm/mach-realview/include/mach/smp.h
arch/arm/mach-realview/platsmp.c
arch/arm/mach-realview/realview_eb.c
arch/arm/mach-realview/realview_pb1176.c
arch/arm/mach-realview/realview_pb11mp.c
arch/arm/mach-realview/realview_pba8.c
arch/arm/mach-realview/realview_pbx.c
arch/arm/mach-s3c2412/Kconfig
arch/arm/mach-s3c2412/Makefile
arch/arm/mach-s3c2416/Kconfig
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv310/cpu.c
arch/arm/mach-s5pv310/hotplug.c
arch/arm/mach-s5pv310/include/mach/smp.h
arch/arm/mach-s5pv310/platsmp.c
arch/arm/mach-s5pv310/time.c
arch/arm/mach-sa1100/Kconfig
arch/arm/mach-sa1100/Makefile
arch/arm/mach-sa1100/cpu-sa1100.c
arch/arm/mach-sa1100/cpu-sa1110.c
arch/arm/mach-sa1100/generic.c
arch/arm/mach-sa1100/include/mach/hardware.h
arch/arm/mach-sa1100/include/mach/nanoengine.h [new file with mode: 0644]
arch/arm/mach-sa1100/nanoengine.c [new file with mode: 0644]
arch/arm/mach-sa1100/pci-nanoengine.c [new file with mode: 0644]
arch/arm/mach-sa1100/simpad.c
arch/arm/mach-sa1100/time.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/clock-sh7367.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh7377.c
arch/arm/mach-shmobile/include/mach/entry-macro.S
arch/arm/mach-shmobile/include/mach/head-ap4evb.txt [new file with mode: 0644]
arch/arm/mach-shmobile/include/mach/vmalloc.h
arch/arm/mach-shmobile/include/mach/zboot.h [new file with mode: 0644]
arch/arm/mach-shmobile/include/mach/zboot_macros.h [new file with mode: 0644]
arch/arm/mach-tcc8k/clock.c
arch/arm/mach-tcc8k/time.c
arch/arm/mach-tegra/clock.c
arch/arm/mach-tegra/clock.h
arch/arm/mach-tegra/hotplug.c
arch/arm/mach-tegra/include/mach/entry-macro.S
arch/arm/mach-tegra/include/mach/io.h
arch/arm/mach-tegra/include/mach/smp.h
arch/arm/mach-tegra/irq.c
arch/arm/mach-tegra/platsmp.c
arch/arm/mach-tegra/tegra2_clocks.c
arch/arm/mach-tegra/timer.c
arch/arm/mach-u300/clock.c
arch/arm/mach-u300/timer.c
arch/arm/mach-ux500/clock.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-ux500/headsmp.S
arch/arm/mach-ux500/hotplug.c
arch/arm/mach-ux500/include/mach/entry-macro.S
arch/arm/mach-ux500/include/mach/smp.h
arch/arm/mach-ux500/platsmp.c
arch/arm/mach-versatile/Kconfig
arch/arm/mach-versatile/core.c
arch/arm/mach-vexpress/Makefile
arch/arm/mach-vexpress/core.h
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/hotplug.c [new file with mode: 0644]
arch/arm/mach-vexpress/include/mach/entry-macro.S
arch/arm/mach-vexpress/include/mach/smp.h
arch/arm/mach-vexpress/platsmp.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-w90x900/clock.h
arch/arm/mach-w90x900/time.c
arch/arm/mm/Kconfig
arch/arm/mm/Makefile
arch/arm/mm/cache-feroceon-l2.c
arch/arm/mm/cache-xsc3l2.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/fault-armv.c
arch/arm/mm/fault.c
arch/arm/mm/flush.c
arch/arm/mm/highmem.c
arch/arm/mm/idmap.c [new file with mode: 0644]
arch/arm/mm/ioremap.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/mm/pgd.c
arch/arm/mm/proc-macros.S
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xscale.S
arch/arm/plat-iop/time.c
arch/arm/plat-mxc/epit.c
arch/arm/plat-mxc/time.c
arch/arm/plat-nomadik/Kconfig
arch/arm/plat-nomadik/timer.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/include/plat/clkdev_omap.h
arch/arm/plat-omap/include/plat/io.h
arch/arm/plat-omap/include/plat/memory.h
arch/arm/plat-omap/include/plat/smp.h
arch/arm/plat-orion/time.c
arch/arm/plat-s3c24xx/Kconfig
arch/arm/plat-spear/include/plat/clock.h
arch/arm/plat-spear/time.c
arch/arm/plat-stmp3xxx/clock.c
arch/arm/plat-stmp3xxx/timer.c
arch/arm/plat-versatile/Makefile
arch/arm/plat-versatile/include/plat/sched_clock.h [new file with mode: 0644]
arch/arm/plat-versatile/sched-clock.c
arch/arm/vfp/vfpmodule.c
arch/mips/Kconfig
arch/mips/alchemy/common/platform.c
arch/mips/alchemy/devboards/prom.c
arch/mips/ar7/clock.c
arch/mips/ar7/time.c
arch/mips/bcm47xx/setup.c
arch/mips/include/asm/cpu.h
arch/mips/include/asm/elf.h
arch/mips/include/asm/io.h
arch/mips/include/asm/mach-ar7/ar7.h
arch/mips/include/asm/mach-bcm47xx/nvram.h
arch/mips/jz4740/board-qi_lb60.c
arch/mips/jz4740/platform.c
arch/mips/jz4740/prom.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/linux32.c
arch/mips/kernel/process.c
arch/mips/kernel/prom.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/traps.c
arch/mips/kernel/vpe.c
arch/mips/lib/memset.S
arch/mips/loongson/common/env.c
arch/mips/math-emu/cp1emu.c
arch/mips/mm/dma-default.c
arch/mips/mm/sc-mips.c
arch/mips/pmc-sierra/yosemite/py-console.c
arch/mips/sibyte/swarm/setup.c
arch/mn10300/kernel/irq.c
arch/mn10300/kernel/time.c
arch/powerpc/platforms/52xx/mpc52xx_gpt.c
arch/sh/Kconfig
arch/sh/boards/mach-highlander/setup.c
arch/sh/boards/mach-se/7206/irq.c
arch/sh/include/asm/clkdev.h
arch/sh/kernel/Makefile
arch/sh/kernel/clkdev.c [deleted file]
arch/sh/kernel/cpu/clock-cpg.c
arch/sh/kernel/cpu/clock.c
arch/sh/kernel/cpu/sh2a/clock-sh7201.c
arch/sh/kernel/cpu/sh4/clock-sh4-202.c
arch/sh/kernel/cpu/sh4a/clock-sh7343.c
arch/sh/kernel/cpu/sh4a/clock-sh7366.c
arch/sh/kernel/cpu/sh4a/clock-sh7722.c
arch/sh/kernel/cpu/sh4a/clock-sh7723.c
arch/sh/kernel/cpu/sh4a/clock-sh7724.c
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
arch/sh/kernel/cpu/sh4a/clock-sh7763.c
arch/sh/kernel/cpu/sh4a/clock-sh7780.c
arch/sh/kernel/cpu/sh4a/clock-sh7785.c
arch/sh/kernel/cpu/sh4a/clock-sh7786.c
arch/sh/kernel/cpu/sh4a/clock-shx3.c
arch/tile/include/asm/signal.h
arch/tile/kernel/compat_signal.c
arch/tile/kernel/intvec_32.S
arch/tile/kernel/process.c
arch/tile/kernel/signal.c
arch/x86/boot/compressed/misc.c
arch/x86/include/asm/e820.h
arch/x86/include/asm/kvm_host.h
arch/x86/kernel/Makefile
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/probe_64.c
arch/x86/kernel/head_32.S
arch/x86/kernel/hpet.c
arch/x86/kernel/microcode_intel.c
arch/x86/kernel/resource.c [new file with mode: 0644]
arch/x86/kernel/setup.c
arch/x86/kernel/xsave.c
arch/x86/kvm/i8259.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/kvm/x86.h
arch/x86/lguest/boot.c
arch/x86/lguest/i386_head.S
arch/x86/oprofile/op_model_amd.c
arch/x86/pci/i386.c
arch/x86/vdso/Makefile
block/blk-map.c
block/blk-merge.c
block/blk-settings.c
block/blk-sysfs.c
block/blk-throttle.c
drivers/Kconfig
drivers/Makefile
drivers/acpi/acpica/evgpeinit.c
drivers/acpi/battery.c
drivers/acpi/scan.c
drivers/amba/bus.c
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-sff.c
drivers/ata/pata_cs5536.c
drivers/atm/atmtcp.c
drivers/block/cciss.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_req.h
drivers/block/drbd/drbd_worker.c
drivers/bluetooth/hci_ldisc.c
drivers/char/agp/intel-gtt.c
drivers/char/ramoops.c
drivers/clk/Kconfig [new file with mode: 0644]
drivers/clk/Makefile [new file with mode: 0644]
drivers/clk/clkdev.c [moved from arch/arm/common/clkdev.c with 93% similarity]
drivers/clocksource/sh_cmt.c
drivers/dma/mv_xor.c
drivers/gpio/cs5535-gpio.c
drivers/gpio/gpiolib.c
drivers/gpio/rdc321x-gpio.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/i915/dvo_ch7017.c
drivers/gpu/drm/i915/i915_dma.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_ringbuffer.c
drivers/gpu/drm/i915/intel_ringbuffer.h
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_fb.c
drivers/hwmon/s3c-hwmon.c
drivers/input/evdev.c
drivers/input/tablet/wacom_wac.c
drivers/isdn/gigaset/capi.c
drivers/leds/led-class.c
drivers/md/dm-table.c
drivers/md/md.c
drivers/media/IR/keymaps/rc-rc6-mce.c
drivers/media/IR/lirc_dev.c
drivers/media/IR/mceusb.c
drivers/media/IR/nuvoton-cir.c
drivers/media/IR/streamzap.c
drivers/media/common/saa7146_hlp.c
drivers/media/common/saa7146_video.c
drivers/media/radio/radio-aimslab.c
drivers/media/radio/radio-aztech.c
drivers/media/radio/radio-cadet.c
drivers/media/radio/radio-gemtek-pci.c
drivers/media/radio/radio-gemtek.c
drivers/media/radio/radio-maestro.c
drivers/media/radio/radio-maxiradio.c
drivers/media/radio/radio-miropcm20.c
drivers/media/radio/radio-rtrack2.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-terratec.c
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-trust.c
drivers/media/radio/radio-typhoon.c
drivers/media/radio/radio-zoltrix.c
drivers/media/video/arv.c
drivers/media/video/bt8xx/bttv-driver.c
drivers/media/video/bw-qcam.c
drivers/media/video/c-qcam.c
drivers/media/video/cafe_ccic.c
drivers/media/video/cx18/cx18-alsa-pcm.c
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx88/cx88-alsa.c
drivers/media/video/cx88/cx88-cards.c
drivers/media/video/cx88/cx88-video.c
drivers/media/video/cx88/cx88.h
drivers/media/video/em28xx/em28xx-video.c
drivers/media/video/et61x251/et61x251_core.c
drivers/media/video/gspca/sonixj.c
drivers/media/video/meye.c
drivers/media/video/mx2_camera.c
drivers/media/video/pms.c
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/s5p-fimc/fimc-core.h
drivers/media/video/s5p-fimc/regs-fimc.h
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sh_vou.c
drivers/media/video/sn9c102/sn9c102_core.c
drivers/media/video/soc_camera.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_queue.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvc_video.c
drivers/media/video/uvc/uvcvideo.h
drivers/media/video/v4l2-dev.c
drivers/media/video/v4l2-device.c
drivers/media/video/w9966.c
drivers/media/video/wm8775.c
drivers/mfd/ab8500-core.c
drivers/mfd/wm831x-core.c
drivers/mmc/core/core.c
drivers/mmc/host/at91_mci.c
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/mmci.c
drivers/mmc/host/mmci.h
drivers/net/atl1c/atl1c_main.c
drivers/net/atlx/atl1.c
drivers/net/benet/be.h
drivers/net/benet/be_cmds.c
drivers/net/benet/be_main.c
drivers/net/bonding/bond_ipv6.c
drivers/net/bonding/bond_main.c
drivers/net/bonding/bonding.h
drivers/net/cnic.c
drivers/net/ehea/ehea_ethtool.c
drivers/net/epic100.c
drivers/net/hamachi.c
drivers/net/pcmcia/axnet_cs.c
drivers/net/pcmcia/pcnet_cs.c
drivers/net/ppp_generic.c
drivers/net/skfp/skfddi.c
drivers/net/starfire.c
drivers/net/sundance.c
drivers/net/tehuti.c
drivers/net/tg3.c
drivers/net/typhoon.c
drivers/net/usb/asix.c
drivers/net/usb/mcs7830.c
drivers/net/veth.c
drivers/net/wireless/hostap/hostap_main.c
drivers/net/wireless/iwlwifi/iwl-1000.c
drivers/net/wireless/iwlwifi/iwl-6000.c
drivers/net/wireless/iwlwifi/iwl-agn-eeprom.c
drivers/net/wireless/iwlwifi/iwl-agn-lib.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-eeprom.h
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/yellowfin.c
drivers/of/of_i2c.c
drivers/pci/bus.c
drivers/pci/dmar.c
drivers/pci/hotplug/pciehp_acpi.c
drivers/pci/quirks.c
drivers/pcmcia/Makefile
drivers/pcmcia/sa1100_generic.c
drivers/pcmcia/sa1100_generic.h
drivers/pcmcia/sa1100_nanoengine.c [new file with mode: 0644]
drivers/pcmcia/soc_common.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_ips.h [new file with mode: 0644]
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-sa1100.c
drivers/scsi/bfa/bfa_fcs.c
drivers/scsi/bfa/bfa_fcs_fcpim.c
drivers/scsi/bfa/bfa_fcs_lport.c
drivers/scsi/bfa/bfa_fcs_rport.c
drivers/scsi/bfa/bfa_ioc.c
drivers/scsi/bfa/bfa_svc.c
drivers/scsi/bfa/bfad.c
drivers/scsi/bfa/bfad_drv.h
drivers/scsi/bfa/bfad_im.c
drivers/scsi/scsi_lib.c
drivers/serial/amba-pl011.c
drivers/sh/intc/core.c
drivers/spi/coldfire_qspi.c
drivers/spi/mpc52xx_spi.c
drivers/spi/omap2_mcspi.c
drivers/spi/spi.c
drivers/spi/spi_fsl_espi.c
drivers/staging/cx25821/cx25821-video.c
drivers/staging/cx25821/cx25821-video.h
drivers/staging/zram/zram_drv.c
drivers/tty/n_gsm.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/core/Kconfig
drivers/usb/gadget/composite.c
drivers/usb/host/xhci-mem.c
drivers/usb/misc/uss720.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/storage/unusual_devs.h
drivers/video/backlight/cr_bllcd.c
drivers/video/fbmem.c
drivers/video/imxfb.c
drivers/video/omap/Kconfig
drivers/video/omap2/vram.c
drivers/video/sh_mobile_hdmi.c
drivers/video/sh_mobile_lcdcfb.c
drivers/watchdog/rdc321x_wdt.c
fs/btrfs/export.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ext4/resize.c
fs/logfs/journal.c
fs/logfs/readwrite.c
fs/namei.c
fs/nilfs2/gcinode.c
fs/nilfs2/ioctl.c
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
fs/notify/inotify/inotify_user.c
fs/ocfs2/aops.c
fs/ocfs2/aops.h
fs/ocfs2/cluster/masklog.c
fs/ocfs2/cluster/masklog.h
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/file.c
fs/ocfs2/ocfs2_fs.h
fs/proc/vmcore.c
include/linux/amba/bus.h
include/linux/amba/serial.h
include/linux/blkdev.h
include/linux/bootmem.h
include/linux/ceph/libceph.h
include/linux/clkdev.h [new file with mode: 0644]
include/linux/cnt32_to_63.h
include/linux/crash_dump.h
include/linux/dmaengine.h
include/linux/fanotify.h
include/linux/fsnotify.h
include/linux/fsnotify_backend.h
include/linux/input.h
include/linux/ioport.h
include/linux/kthread.h
include/linux/netlink.h
include/linux/perf_event.h
include/linux/pm_runtime.h
include/linux/sched.h
include/linux/ssb/ssb_driver_gige.h
include/linux/taskstats.h
include/linux/unaligned/packed_struct.h
include/media/saa7146.h
include/media/v4l2-device.h
include/media/wm8775.h
include/net/flow.h
include/net/ip6_route.h
include/net/mac80211.h
include/net/pkt_cls.h
include/net/sch_generic.h
include/net/sock.h
init/do_mounts.c
kernel/fork.c
kernel/kthread.c
kernel/perf_event.c
kernel/power/swap.c
kernel/power/user.c
kernel/resource.c
kernel/sched.c
kernel/taskstats.c
kernel/time/clocksource.c
kernel/timer.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/user.c
kernel/watchdog.c
mm/compaction.c
mm/memcontrol.c
mm/migrate.c
mm/nommu.c
mm/page-writeback.c
mm/percpu.c
net/bluetooth/rfcomm/core.c
net/bridge/br_multicast.c
net/bridge/br_stp_bpdu.c
net/can/bcm.c
net/ceph/messenger.c
net/ceph/pagevec.c
net/core/fib_rules.c
net/core/sock.c
net/ipv4/fib_frontend.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv4/udp.c
net/ipv4/udplite.c
net/ipv6/addrconf.c
net/ipv6/ip6_output.c
net/ipv6/route.c
net/ipv6/udp.c
net/ipv6/udplite.c
net/ipv6/xfrm6_output.c
net/irda/af_irda.c
net/mac80211/ibss.c
net/mac80211/rx.c
net/mac80211/work.c
net/sched/sch_sfq.c
net/sctp/socket.c
scripts/kconfig/menu.c
scripts/recordmcount.c
scripts/recordmcount.h
scripts/tags.sh
security/integrity/ima/ima_policy.c
security/keys/request_key.c
sound/core/pcm_lib.c
sound/oss/soundcard.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/codecs/max98088.c
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8741.c
sound/soc/codecs/wm8753.c
sound/soc/codecs/wm8904.c
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8955.c
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8962.c
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9090.c
sound/soc/soc-dapm.c
tools/perf/builtin-buildid-list.c
tools/perf/builtin-probe.c
tools/perf/util/header.c
tools/perf/util/hist.c
tools/perf/util/probe-event.c
tools/perf/util/probe-finder.c
tools/perf/util/string.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h

index a2976a6de033df2b4247f69b48f56f44abed3378..e9c77788a39d8f2c5c807b59295be6c3f1b3fea6 100644 (file)
@@ -516,6 +516,7 @@ int main(int argc, char *argv[])
                        default:
                                fprintf(stderr, "Unknown nla_type %d\n",
                                        na->nla_type);
+                       case TASKSTATS_TYPE_NULL:
                                break;
                        }
                        na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
index ecf7d04bca2601d79e8239b08a777c207198b451..91c24a1e8a9ef14d209bb7c3fa655fef6c81149b 100644 (file)
@@ -34,3 +34,5 @@ memory.txt
        - description of the virtual memory layout
 nwfpe/
        - NWFPE floating point emulator documentation
+swp_emulation
+       - SWP/SWPB emulation handler/logging description
diff --git a/Documentation/arm/swp_emulation b/Documentation/arm/swp_emulation
new file mode 100644 (file)
index 0000000..af903d2
--- /dev/null
@@ -0,0 +1,27 @@
+Software emulation of deprecated SWP instruction (CONFIG_SWP_EMULATE)
+---------------------------------------------------------------------
+
+ARMv6 architecture deprecates use of the SWP/SWPB instructions, and recommeds
+moving to the load-locked/store-conditional instructions LDREX and STREX.
+
+ARMv7 multiprocessing extensions introduce the ability to disable these
+instructions, triggering an undefined instruction exception when executed.
+Trapped instructions are emulated using an LDREX/STREX or LDREXB/STREXB
+sequence. If a memory access fault (an abort) occurs, a segmentation fault is
+signalled to the triggering process.
+
+/proc/cpu/swp_emulation holds some statistics/information, including the PID of
+the last process to trigger the emulation to be invocated. For example:
+---
+Emulated SWP:          12
+Emulated SWPB:         0
+Aborted SWP{B}:                1
+Last process:          314
+---
+
+NOTE: when accessing uncached shared regions, LDREX/STREX rely on an external
+transaction monitoring block called a global monitor to maintain update
+atomicity. If your system does not implement a global monitor, this option can
+cause programs that perform SWP operations to uncached memory to deadlock, as
+the STREX operation will always fail.
+
index b6426f15b4ae85f5469b962806004237b9b5607e..33fa3e5d38fd7480d2ddd136b68f77fef7734c1d 100644 (file)
@@ -18,7 +18,6 @@ prototypes:
        char *(*d_dname)((struct dentry *dentry, char *buffer, int buflen);
 
 locking rules:
-       none have BKL
                dcache_lock     rename_lock     ->d_lock        may block
 d_revalidate:  no              no              no              yes
 d_hash         no              no              no              yes
@@ -42,18 +41,23 @@ ata *);
        int (*rename) (struct inode *, struct dentry *,
                        struct inode *, struct dentry *);
        int (*readlink) (struct dentry *, char __user *,int);
-       int (*follow_link) (struct dentry *, struct nameidata *);
+       void * (*follow_link) (struct dentry *, struct nameidata *);
+       void (*put_link) (struct dentry *, struct nameidata *, void *);
        void (*truncate) (struct inode *);
        int (*permission) (struct inode *, int, struct nameidata *);
+       int (*check_acl)(struct inode *, int);
        int (*setattr) (struct dentry *, struct iattr *);
        int (*getattr) (struct vfsmount *, struct dentry *, struct kstat *);
        int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
        ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        int (*removexattr) (struct dentry *, const char *);
+       void (*truncate_range)(struct inode *, loff_t, loff_t);
+       long (*fallocate)(struct inode *inode, int mode, loff_t offset, loff_t len);
+       int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
 
 locking rules:
-       all may block, none have BKL
+       all may block
                i_mutex(inode)
 lookup:                yes
 create:                yes
@@ -66,19 +70,24 @@ rmdir:              yes (both)      (see below)
 rename:                yes (all)       (see below)
 readlink:      no
 follow_link:   no
+put_link:      no
 truncate:      yes             (see below)
 setattr:       yes
 permission:    no
+check_acl:     no
 getattr:       no
 setxattr:      yes
 getxattr:      no
 listxattr:     no
 removexattr:   yes
+truncate_range:        yes
+fallocate:     no
+fiemap:                no
        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() - library function normally used by
+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).
@@ -91,7 +100,7 @@ prototypes:
        struct inode *(*alloc_inode)(struct super_block *sb);
        void (*destroy_inode)(struct inode *);
        void (*dirty_inode) (struct inode *);
-       int (*write_inode) (struct inode *, int);
+       int (*write_inode) (struct inode *, struct writeback_control *wbc);
        int (*drop_inode) (struct inode *);
        void (*evict_inode) (struct inode *);
        void (*put_super) (struct super_block *);
@@ -105,10 +114,10 @@ prototypes:
        int (*show_options)(struct seq_file *, struct vfsmount *);
        ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
        ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
+       int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
 
 locking rules:
        All may block [not true, see below]
-       None have BKL
                        s_umount
 alloc_inode:
 destroy_inode:
@@ -127,6 +136,7 @@ umount_begin:               no
 show_options:          no              (namespace_sem)
 quota_read:            no              (see below)
 quota_write:           no              (see below)
+bdev_try_to_free_page: no              (see below)
 
 ->statfs() has s_umount (shared) when called by ustat(2) (native or
 compat), but that's an accident of bad API; s_umount is used to pin
@@ -139,19 +149,25 @@ be the only ones operating on the quota file by the quota code (via
 dqio_sem) (unless an admin really wants to screw up something and
 writes to quota files with quotas on). For other details about locking
 see also dquot_operations section.
+->bdev_try_to_free_page is called from the ->releasepage handler of
+the block device inode.  See there for more details.
 
 --------------------------- file_system_type ---------------------------
 prototypes:
        int (*get_sb) (struct file_system_type *, int,
                       const char *, void *, struct vfsmount *);
+       struct dentry *(*mount) (struct file_system_type *, int,
+                      const char *, void *);
        void (*kill_sb) (struct super_block *);
 locking rules:
-               may block       BKL
-get_sb         yes             no
-kill_sb                yes             no
+               may block
+get_sb         yes
+mount          yes
+kill_sb                yes
 
 ->get_sb() returns error or 0 with locked superblock attached to the vfsmount
 (exclusive on ->s_umount).
+->mount() returns ERR_PTR or the root dentry.
 ->kill_sb() takes a write-locked superblock, does all shutdown work on it,
 unlocks and drops the reference.
 
@@ -176,27 +192,35 @@ prototypes:
        void (*freepage)(struct page *);
        int (*direct_IO)(int, struct kiocb *, const struct iovec *iov,
                        loff_t offset, unsigned long nr_segs);
-       int (*launder_page) (struct page *);
+       int (*get_xip_mem)(struct address_space *, pgoff_t, int, void **,
+                               unsigned long *);
+       int (*migratepage)(struct address_space *, struct page *, struct page *);
+       int (*launder_page)(struct page *);
+       int (*is_partially_uptodate)(struct page *, read_descriptor_t *, unsigned long);
+       int (*error_remove_page)(struct address_space *, struct page *);
 
 locking rules:
        All except set_page_dirty and freepage may block
 
-                       BKL     PageLocked(page)        i_mutex
-writepage:             no      yes, unlocks (see below)
-readpage:              no      yes, unlocks
-sync_page:             no      maybe
-writepages:            no
-set_page_dirty         no      no
-readpages:             no
-write_begin:           no      locks the page          yes
-write_end:             no      yes, unlocks            yes
-perform_write:         no      n/a                     yes
-bmap:                  no
-invalidatepage:                no      yes
-releasepage:           no      yes
-freepage:              no      yes
-direct_IO:             no
-launder_page:          no      yes
+                       PageLocked(page)        i_mutex
+writepage:             yes, unlocks (see below)
+readpage:              yes, unlocks
+sync_page:             maybe
+writepages:
+set_page_dirty         no
+readpages:
+write_begin:           locks the page          yes
+write_end:             yes, unlocks            yes
+bmap:
+invalidatepage:                yes
+releasepage:           yes
+freepage:              yes
+direct_IO:
+get_xip_mem:                                   maybe
+migratepage:           yes (both)
+launder_page:          yes
+is_partially_uptodate: yes
+error_remove_page:     yes
 
        ->write_begin(), ->write_end(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
@@ -276,9 +300,8 @@ under spinlock (it cannot block) and is sometimes called with the page
 not locked.
 
        ->bmap() is currently used by legacy ioctl() (FIBMAP) provided by some
-filesystems and by the swapper. The latter will eventually go away. All
-instances do not actually need the BKL. Please, keep it that way and don't
-breed new callers.
+filesystems and by the swapper. The latter will eventually go away.  Please,
+keep it that way and don't breed new callers.
 
        ->invalidatepage() is called when the filesystem must attempt to drop
 some or all of the buffers from the page when it is being truncated.  It
@@ -299,47 +322,37 @@ cleaned, or an error value if not. Note that in order to prevent the page
 getting mapped back in and redirtied, it needs to be kept locked
 across the entire operation.
 
-       Note: currently almost all instances of address_space methods are
-using BKL for internal serialization and that's one of the worst sources
-of contention. Normally they are calling library functions (in fs/buffer.c)
-and pass foo_get_block() as a callback (on local block-based filesystems,
-indeed). BKL is not needed for library stuff and is usually taken by
-foo_get_block(). It's an overkill, since block bitmaps can be protected by
-internal fs locking and real critical areas are much smaller than the areas
-filesystems protect now.
-
 ----------------------- file_lock_operations ------------------------------
 prototypes:
-       void (*fl_insert)(struct file_lock *);  /* lock insertion callback */
-       void (*fl_remove)(struct file_lock *);  /* lock removal callback */
        void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
        void (*fl_release_private)(struct file_lock *);
 
 
 locking rules:
-                       BKL     may block
-fl_insert:             yes     no
-fl_remove:             yes     no
-fl_copy_lock:          yes     no
-fl_release_private:    yes     yes
+                       file_lock_lock  may block
+fl_copy_lock:          yes             no
+fl_release_private:    maybe           no
 
 ----------------------- lock_manager_operations ---------------------------
 prototypes:
        int (*fl_compare_owner)(struct file_lock *, struct file_lock *);
        void (*fl_notify)(struct file_lock *);  /* unblock callback */
+       int (*fl_grant)(struct file_lock *, struct file_lock *, int);
        void (*fl_release_private)(struct file_lock *);
        void (*fl_break)(struct file_lock *); /* break_lease callback */
+       int (*fl_mylease)(struct file_lock *, struct file_lock *);
+       int (*fl_change)(struct file_lock **, int);
 
 locking rules:
-                       BKL     may block
-fl_compare_owner:      yes     no
-fl_notify:             yes     no
-fl_release_private:    yes     yes
-fl_break:              yes     no
-
-       Currently only NFSD and NLM provide instances of this class. None of the
-them block. If you have out-of-tree instances - please, show up. Locking
-in that area will change.
+                       file_lock_lock  may block
+fl_compare_owner:      yes             no
+fl_notify:             yes             no
+fl_grant:              no              no
+fl_release_private:    maybe           no
+fl_break:              yes             no
+fl_mylease:            yes             no
+fl_change              yes             no
+
 --------------------------- buffer_head -----------------------------------
 prototypes:
        void (*b_end_io)(struct buffer_head *bh, int uptodate);
@@ -364,17 +377,17 @@ prototypes:
        void (*swap_slot_free_notify) (struct block_device *, unsigned long);
 
 locking rules:
-                       BKL     bd_mutex
-open:                  no      yes
-release:               no      yes
-ioctl:                 no      no
-compat_ioctl:          no      no
-direct_access:         no      no
-media_changed:         no      no
-unlock_native_capacity:        no      no
-revalidate_disk:       no      no
-getgeo:                        no      no
-swap_slot_free_notify: no      no      (see below)
+                       bd_mutex
+open:                  yes
+release:               yes
+ioctl:                 no
+compat_ioctl:          no
+direct_access:         no
+media_changed:         no
+unlock_native_capacity:        no
+revalidate_disk:       no
+getgeo:                        no
+swap_slot_free_notify: no      (see below)
 
 media_changed, unlock_native_capacity and revalidate_disk are called only from
 check_disk_change().
@@ -413,34 +426,21 @@ prototypes:
        unsigned long (*get_unmapped_area)(struct file *, unsigned long,
                        unsigned long, unsigned long, unsigned long);
        int (*check_flags)(int);
+       int (*flock) (struct file *, int, struct file_lock *);
+       ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *,
+                       size_t, unsigned int);
+       ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *,
+                       size_t, unsigned int);
+       int (*setlease)(struct file *, long, struct file_lock **);
 };
 
 locking rules:
-       All may block.
-                       BKL
-llseek:                        no      (see below)
-read:                  no
-aio_read:              no
-write:                 no
-aio_write:             no
-readdir:               no
-poll:                  no
-unlocked_ioctl:                no
-compat_ioctl:          no
-mmap:                  no
-open:                  no
-flush:                 no
-release:               no
-fsync:                 no      (see below)
-aio_fsync:             no
-fasync:                        no
-lock:                  yes
-readv:                 no
-writev:                        no
-sendfile:              no
-sendpage:              no
-get_unmapped_area:     no
-check_flags:           no
+       All may block except for ->setlease.
+       No VFS locks held on entry except for ->fsync and ->setlease.
+
+->fsync() has i_mutex on inode.
+
+->setlease has the file_list_lock held and must not sleep.
 
 ->llseek() locking has moved from llseek to the individual llseek
 implementations.  If your fs is not using generic_file_llseek, you
@@ -450,17 +450,10 @@ mutex or just to use i_size_read() instead.
 Note: this does not protect the file->f_pos against concurrent modifications
 since this is something the userspace has to take care about.
 
-Note: ext2_release() was *the* source of contention on fs-intensive
-loads and dropping BKL on ->release() helps to get rid of that (we still
-grab BKL for cases when we close a file that had been opened r/w, but that
-can and should be done using the internal locking with smaller critical areas).
-Current worst offender is ext2_get_block()...
-
-->fasync() is called without BKL protection, and is responsible for
-maintaining the FASYNC bit in filp->f_flags.  Most instances call
-fasync_helper(), which does that maintenance, so it's not normally
-something one needs to worry about.  Return values > 0 will be mapped to
-zero in the VFS layer.
+->fasync() is responsible for maintaining the FASYNC bit in filp->f_flags.
+Most instances call fasync_helper(), which does that maintenance, so it's
+not normally something one needs to worry about.  Return values > 0 will be
+mapped to zero in the VFS layer.
 
 ->readdir() and ->ioctl() on directories must be changed. Ideally we would
 move ->readdir() to inode_operations and use a separate method for directory
@@ -471,8 +464,6 @@ components. And there are other reasons why the current interface is a mess...
 ->read on directories probably must go away - we should just enforce -EISDIR
 in sys_read() and friends.
 
-->fsync() has i_mutex on inode.
-
 --------------------------- dquot_operations -------------------------------
 prototypes:
        int (*write_dquot) (struct dquot *);
@@ -507,12 +498,12 @@ prototypes:
        int (*access)(struct vm_area_struct *, unsigned long, void*, int, int);
 
 locking rules:
-               BKL     mmap_sem        PageLocked(page)
-open:          no      yes
-close:         no      yes
-fault:         no      yes             can return with page locked
-page_mkwrite:  no      yes             can return with page locked
-access:                no      yes
+               mmap_sem        PageLocked(page)
+open:          yes
+close:         yes
+fault:         yes             can return with page locked
+page_mkwrite:  yes             can return with page locked
+access:                yes
 
        ->fault() is called when a previously not present pte is about
 to be faulted in. The filesystem must find and return the page associated
@@ -539,6 +530,3 @@ VM_IO | VM_PFNMAP VMAs.
 
 (if you break something or notice that it is broken and do not fix it yourself
 - at least put it here)
-
-ipc/shm.c::shm_delete() - may need BKL.
-->read() and ->write() in many drivers are (probably) missing BKL.
index cdd2a6e8a3b79ae9fabc67230a27a21927642c9b..01ece1b9213e97de22f1cc02faf4f0bae5165e96 100644 (file)
@@ -1759,7 +1759,7 @@ and is between 256 and 4096 characters. It is defined in the file
 
        nousb           [USB] Disable the USB subsystem
 
-       nowatchdog      [KNL] Disable the lockup detector.
+       nowatchdog      [KNL] Disable the lockup detector (NMI watchdog).
 
        nowb            [ARM]
 
@@ -2175,11 +2175,6 @@ and is between 256 and 4096 characters. It is defined in the file
        reset_devices   [KNL] Force drivers to reset the underlying device
                        during initialization.
 
-       resource_alloc_from_bottom
-                       Allocate new resources from the beginning of available
-                       space, not the end.  If you need to use this, please
-                       report a bug.
-
        resume=         [SWSUSP]
                        Specify the partition device for software suspend
 
index 489e9bacd165ad4a354130edcf7e03d97471b52b..41cc7b30d7ddaff700a198b590eb91047d90d0d0 100644 (file)
@@ -379,8 +379,8 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
       zero)
 
   bool pm_runtime_suspended(struct device *dev);
-    - return true if the device's runtime PM status is 'suspended', or false
-      otherwise
+    - return true if the device's runtime PM status is 'suspended' and its
+      'power.disable_depth' field is equal to zero, or false otherwise
 
   void pm_runtime_allow(struct device *dev);
     - set the power.runtime_auto flag for the device and decrease its usage
index 570ef2b3d79b16c2f57c01f88d5de3a1a954f6a4..df322c1034667eebbced0792f2c8a7c733e5cf78 100644 (file)
@@ -1044,9 +1044,9 @@ Details:
 
 
 /**
- *      queuecommand - queue scsi command, invoke 'done' on completion
+ *      queuecommand - queue scsi command, invoke scp->scsi_done on completion
+ *      @shost: pointer to the scsi host object
  *      @scp: pointer to scsi command object
- *      @done: function pointer to be invoked on completion
  *
  *      Returns 0 on success.
  *
@@ -1074,42 +1074,45 @@ Details:
  *
  *      Other types of errors that are detected immediately may be
  *      flagged by setting scp->result to an appropriate value,
- *      invoking the 'done' callback, and then returning 0 from this
- *      function. If the command is not performed immediately (and the
- *      LLD is starting (or will start) the given command) then this
- *      function should place 0 in scp->result and return 0.
+ *      invoking the scp->scsi_done callback, and then returning 0
+ *      from this function. If the command is not performed
+ *      immediately (and the LLD is starting (or will start) the given
+ *      command) then this function should place 0 in scp->result and
+ *      return 0.
  *
  *      Command ownership.  If the driver returns zero, it owns the
- *      command and must take responsibility for ensuring the 'done'
- *      callback is executed.  Note: the driver may call done before
- *      returning zero, but after it has called done, it may not
- *      return any value other than zero.  If the driver makes a
- *      non-zero return, it must not execute the command's done
- *      callback at any time.
- *
- *      Locks: struct Scsi_Host::host_lock held on entry (with "irqsave")
- *             and is expected to be held on return.
+ *      command and must take responsibility for ensuring the
+ *      scp->scsi_done callback is executed.  Note: the driver may
+ *      call scp->scsi_done before returning zero, but after it has
+ *      called scp->scsi_done, it may not return any value other than
+ *      zero.  If the driver makes a non-zero return, it must not
+ *      execute the command's scsi_done callback at any time.
+ *
+ *      Locks: up to and including 2.6.36, struct Scsi_Host::host_lock
+ *             held on entry (with "irqsave") and is expected to be
+ *             held on return. From 2.6.37 onwards, queuecommand is
+ *             called without any locks held.
  *
  *      Calling context: in interrupt (soft irq) or process context
  *
- *      Notes: This function should be relatively fast. Normally it will
- *      not wait for IO to complete. Hence the 'done' callback is invoked 
- *      (often directly from an interrupt service routine) some time after
- *      this function has returned. In some cases (e.g. pseudo adapter 
- *      drivers that manufacture the response to a SCSI INQUIRY)
- *      the 'done' callback may be invoked before this function returns.
- *      If the 'done' callback is not invoked within a certain period
- *      the SCSI mid level will commence error processing.
- *      If a status of CHECK CONDITION is placed in "result" when the
- *      'done' callback is invoked, then the LLD driver should 
- *      perform autosense and fill in the struct scsi_cmnd::sense_buffer
+ *      Notes: This function should be relatively fast. Normally it
+ *      will not wait for IO to complete. Hence the scp->scsi_done
+ *      callback is invoked (often directly from an interrupt service
+ *      routine) some time after this function has returned. In some
+ *      cases (e.g. pseudo adapter drivers that manufacture the
+ *      response to a SCSI INQUIRY) the scp->scsi_done callback may be
+ *      invoked before this function returns.  If the scp->scsi_done
+ *      callback is not invoked within a certain period the SCSI mid
+ *      level will commence error processing.  If a status of CHECK
+ *      CONDITION is placed in "result" when the scp->scsi_done
+ *      callback is invoked, then the LLD driver should perform
+ *      autosense and fill in the struct scsi_cmnd::sense_buffer
  *      array. The scsi_cmnd::sense_buffer array is zeroed prior to
  *      the mid level queuing a command to an LLD.
  *
  *      Defined in: LLD
  **/
-    int queuecommand(struct scsi_cmnd * scp, 
-                     void (*done)(struct scsi_cmnd *))
+    int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)
 
 
 /**
index b3e73ddb1567902fdeb9d65e1a661db9bca7780d..12cecc83cd91c658c71524bba59762b83f810829 100644 (file)
@@ -373,9 +373,18 @@ EVENT_PROCESS:
                                print "         $regex_lru_isolate/o\n";
                                next;
                        }
+                       my $isolate_mode = $1;
                        my $nr_scanned = $4;
                        my $nr_contig_dirty = $7;
-                       $perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
+
+                       # To closer match vmstat scanning statistics, only count isolate_both
+                       # and isolate_inactive as scanning. isolate_active is rotation
+                       # isolate_inactive == 0
+                       # isolate_active   == 1
+                       # isolate_both     == 2
+                       if ($isolate_mode != 1) {
+                               $perprocesspid{$process_pid}->{HIGH_NR_SCANNED} += $nr_scanned;
+                       }
                        $perprocesspid{$process_pid}->{HIGH_NR_CONTIG_DIRTY} += $nr_contig_dirty;
                } elsif ($tracepoint eq "mm_vmscan_lru_shrink_inactive") {
                        $details = $5;
index 6a588873cf8d2da8b00f803a1dcd8d96841292bd..7585e9dd835b72f3067e2694b39569779fcc1fde 100644 (file)
@@ -405,7 +405,7 @@ S:  Supported
 F:     drivers/usb/gadget/amd5536udc.*
 
 AMD GEODE PROCESSOR/CHIPSET SUPPORT
-P:     Jordan Crouse
+P:     Andres Salomon <dilinger@queued.net>
 L:     linux-geode@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
 S:     Supported
@@ -792,11 +792,14 @@ S:        Maintained
 
 ARM/NOMADIK ARCHITECTURE
 M:     Alessandro Rubini <rubini@unipv.it>
+M:     Linus Walleij <linus.walleij@stericsson.com>
 M:     STEricsson <STEricsson_nomadik_linux@list.st.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-nomadik/
 F:     arch/arm/plat-nomadik/
+F:     drivers/i2c/busses/i2c-nomadik.c
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
 
 ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
 M:     Nelson Castillo <arhuaco@freaks-unidos.net>
@@ -998,12 +1001,24 @@ F:       drivers/i2c/busses/i2c-stu300.c
 F:     drivers/rtc/rtc-coh901331.c
 F:     drivers/watchdog/coh901327_wdt.c
 F:     drivers/dma/coh901318*
+F:     drivers/mfd/ab3100*
+F:     drivers/rtc/rtc-ab3100.c
+F:     drivers/rtc/rtc-coh901331.c
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
 
-ARM/U8500 ARM ARCHITECTURE
+ARM/Ux500 ARM ARCHITECTURE
 M:     Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
+M:     Linus Walleij <linus.walleij@stericsson.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-ux500/
+F:     drivers/dma/ste_dma40*
+F:     drivers/mfd/ab3550*
+F:     drivers/mfd/abx500*
+F:     drivers/mfd/ab8500*
+F:     drivers/mfd/stmpe*
+F:     drivers/rtc/rtc-ab8500.c
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
 
 ARM/VFP SUPPORT
 M:     Russell King <linux@arm.linux.org.uk>
@@ -4590,7 +4605,7 @@ F:        drivers/pcmcia/
 F:     include/pcmcia/
 
 PCNET32 NETWORK DRIVER
-M:     Don Fry <pcnet32@verizon.net>
+M:     Don Fry <pcnet32@frontier.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/pcnet32.c
index 5aa44278d95686e9719f38592599b094a72a1366..74b25559f831c5c48150789ed3230921635e0ae0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 37
-EXTRAVERSION = -rc6
+EXTRAVERSION =
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index fac58916adecf15dcd7d868d010dcc9bb999b9be..a3fb23be87f3100daf1c5fa9800c756e7cb2821b 100644 (file)
@@ -2,6 +2,7 @@ config ARM
        bool
        default y
        select HAVE_AOUT
+       select HAVE_DMA_API_DEBUG
        select HAVE_IDE
        select HAVE_MEMBLOCK
        select RTC_LIB
@@ -24,6 +25,7 @@ config ARM
        select PERF_USE_VMALLOC
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
+       select HAVE_C_RECORDMCOUNT
        help
          The ARM series is a line of low-power-consumption RISC chip designs
          licensed by ARM Ltd and targeted at embedded applications and
@@ -35,9 +37,15 @@ config ARM
 config HAVE_PWM
        bool
 
+config MIGHT_HAVE_PCI
+       bool
+
 config SYS_SUPPORTS_APM_EMULATION
        bool
 
+config HAVE_SCHED_CLOCK
+       bool
+
 config GENERIC_GPIO
        bool
 
@@ -222,7 +230,7 @@ config ARCH_INTEGRATOR
        bool "ARM Ltd. Integrator family"
        select ARM_AMBA
        select ARCH_HAS_CPUFREQ
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ICST
        select GENERIC_CLOCKEVENTS
        select PLAT_VERSATILE
@@ -232,7 +240,8 @@ config ARCH_INTEGRATOR
 config ARCH_REALVIEW
        bool "ARM Ltd. RealView family"
        select ARM_AMBA
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
+       select HAVE_SCHED_CLOCK
        select ICST
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -246,7 +255,8 @@ config ARCH_VERSATILE
        bool "ARM Ltd. Versatile family"
        select ARM_AMBA
        select ARM_VIC
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
+       select HAVE_SCHED_CLOCK
        select ICST
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
@@ -260,9 +270,10 @@ config ARCH_VEXPRESS
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select ARM_AMBA
        select ARM_TIMER_SP804
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
+       select HAVE_SCHED_CLOCK
        select ICST
        select PLAT_VERSATILE
        help
@@ -281,7 +292,7 @@ config ARCH_BCMRING
        depends on MMU
        select CPU_V6
        select ARM_AMBA
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
        help
@@ -299,6 +310,7 @@ config ARCH_CNS3XXX
        select CPU_V6
        select GENERIC_CLOCKEVENTS
        select ARM_GIC
+       select MIGHT_HAVE_PCI
        select PCI_DOMAINS if PCI
        help
          Support for Cavium Networks CNS3XXX platform.
@@ -328,7 +340,7 @@ config ARCH_EP93XX
        select CPU_ARM920T
        select ARM_AMBA
        select ARM_VIC
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_REQUIRE_GPIOLIB
        select ARCH_HAS_HOLES_MEMORYMODEL
        select ARCH_USES_GETTIMEOFFSET
@@ -348,7 +360,7 @@ config ARCH_MXC
        bool "Freescale MXC/iMX-based"
        select GENERIC_CLOCKEVENTS
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        help
          Support for Freescale MXC/iMX-based family of processors
 
@@ -363,7 +375,7 @@ config ARCH_MXS
 config ARCH_STMP3XXX
        bool "Freescale STMP3xxx"
        select CPU_ARM926T
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
        select USB_ARCH_HAS_EHCI
@@ -442,6 +454,8 @@ config ARCH_IXP4XX
        select CPU_XSCALE
        select GENERIC_GPIO
        select GENERIC_CLOCKEVENTS
+       select HAVE_SCHED_CLOCK
+       select MIGHT_HAVE_PCI
        select DMABOUNCE if PCI
        help
          Support for Intel's IXP4XX (XScale) family of processors.
@@ -481,7 +495,7 @@ config ARCH_LPC32XX
        select HAVE_IDE
        select ARM_AMBA
        select USB_ARCH_HAS_OHCI
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        help
@@ -515,8 +529,9 @@ config ARCH_MMP
        bool "Marvell PXA168/910/MMP2"
        depends on MMU
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
+       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
@@ -548,7 +563,7 @@ config ARCH_W90X900
        bool "Nuvoton W90X900 CPU"
        select CPU_ARM926T
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        help
          Support for Nuvoton (Winbond logic dept.) ARM9 processor,
@@ -562,18 +577,19 @@ config ARCH_W90X900
 config ARCH_NUC93X
        bool "Nuvoton NUC93X CPU"
        select CPU_ARM926T
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        help
          Support for Nuvoton (Winbond logic dept.) NUC93X MCU,The NUC93X is a
          low-power and high performance MPEG-4/JPEG multimedia controller chip.
 
 config ARCH_TEGRA
        bool "NVIDIA Tegra"
+       select CLKDEV_LOOKUP
        select GENERIC_TIME
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select HAVE_SCHED_CLOCK
        select ARCH_HAS_BARRIERS if CACHE_L2X0
        select ARCH_HAS_CPUFREQ
        help
@@ -583,7 +599,7 @@ config ARCH_TEGRA
 config ARCH_PNX4008
        bool "Philips Nexperia PNX4008 Mobile"
        select CPU_ARM926T
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_USES_GETTIMEOFFSET
        help
          This enables support for Philips PNX4008 mobile platform.
@@ -593,9 +609,10 @@ config ARCH_PXA
        depends on MMU
        select ARCH_MTD_XIP
        select ARCH_HAS_CPUFREQ
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
+       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select PLAT_PXA
        select SPARSE_IRQ
@@ -644,6 +661,7 @@ config ARCH_SA1100
        select CPU_FREQ
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
+       select HAVE_SCHED_CLOCK
        select TICK_ONESHOT
        select ARCH_REQUIRE_GPIOLIB
        help
@@ -770,7 +788,7 @@ config ARCH_TCC_926
        bool "Telechips TCC ARM926-based systems"
        select CPU_ARM926T
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        help
          Support for Telechips TCC ARM926-based systems.
@@ -790,11 +808,12 @@ config ARCH_U300
        bool "ST-Ericsson U300 Series"
        depends on MMU
        select CPU_ARM926T
+       select HAVE_SCHED_CLOCK
        select HAVE_TCM
        select ARM_AMBA
        select ARM_VIC
        select GENERIC_CLOCKEVENTS
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_GPIO
        help
          Support for ST-Ericsson U300 series mobile platforms.
@@ -804,7 +823,7 @@ config ARCH_U8500
        select CPU_V7
        select ARM_AMBA
        select GENERIC_CLOCKEVENTS
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select ARCH_REQUIRE_GPIOLIB
        select ARCH_HAS_CPUFREQ
        help
@@ -815,7 +834,7 @@ config ARCH_NOMADIK
        select ARM_AMBA
        select ARM_VIC
        select CPU_ARM926T
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select ARCH_REQUIRE_GPIOLIB
        help
@@ -827,7 +846,7 @@ config ARCH_DAVINCI
        select ARCH_REQUIRE_GPIOLIB
        select ZONE_DMA
        select HAVE_IDE
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_ALLOCATOR
        select ARCH_HAS_HOLES_MEMORYMODEL
        help
@@ -839,6 +858,7 @@ config ARCH_OMAP
        select ARCH_REQUIRE_GPIOLIB
        select ARCH_HAS_CPUFREQ
        select GENERIC_CLOCKEVENTS
+       select HAVE_SCHED_CLOCK
        select ARCH_HAS_HOLES_MEMORYMODEL
        help
          Support for TI's OMAP platform (OMAP1/2/3/4).
@@ -847,7 +867,7 @@ config PLAT_SPEAR
        bool "ST SPEAr"
        select ARM_AMBA
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        help
@@ -994,9 +1014,11 @@ config ARCH_ACORN
 config PLAT_IOP
        bool
        select GENERIC_CLOCKEVENTS
+       select HAVE_SCHED_CLOCK
 
 config PLAT_ORION
        bool
+       select HAVE_SCHED_CLOCK
 
 config PLAT_PXA
        bool
@@ -1029,6 +1051,11 @@ config CPU_HAS_PMU
        default y
        bool
 
+config MULTI_IRQ_HANDLER
+       bool
+       help
+         Allow each machine to specify it's own IRQ handler at run time.
+
 if !MMU
 source "arch/arm/Kconfig-nommu"
 endif
@@ -1176,7 +1203,7 @@ config ISA_DMA_API
        bool
 
 config PCI
-       bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB || ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+       bool "PCI support" if MIGHT_HAVE_PCI
        help
          Find out whether you have a PCI motherboard. PCI is the name of a
          bus system, i.e. the way the CPU talks to the other stuff inside
@@ -1187,6 +1214,12 @@ config PCI_DOMAINS
        bool
        depends on PCI
 
+config PCI_NANOENGINE
+       bool "BSE nanoEngine PCI support"
+       depends on SA1100_NANOENGINE
+       help
+         Enable PCI on the BSE nanoEngine board.
+
 config PCI_SYSCALL
        def_bool PCI
 
@@ -1242,7 +1275,7 @@ config SMP
 config SMP_ON_UP
        bool "Allow booting SMP kernel on uniprocessor systems (EXPERIMENTAL)"
        depends on EXPERIMENTAL
-       depends on SMP && !XIP && !THUMB2_KERNEL
+       depends on SMP && !XIP
        default y
        help
          SMP kernels contain instructions which fail on non-SMP processors.
@@ -1261,6 +1294,7 @@ config HAVE_ARM_SCU
 config HAVE_ARM_TWD
        bool
        depends on SMP
+       select TICK_ONESHOT
        help
          This options enables support for the ARM timer and watchdog unit
 
@@ -1324,7 +1358,7 @@ config HZ
        default 100
 
 config THUMB2_KERNEL
-       bool "Compile the kernel in Thumb-2 mode"
+       bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
        depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
        select AEABI
        select ARM_ASM_UNIFIED
@@ -1538,6 +1572,7 @@ config SECCOMP
 
 config CC_STACKPROTECTOR
        bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
        help
          This option turns on the -fstack-protector GCC feature. This
          feature puts, at the beginning of functions, a canary value on
@@ -1664,6 +1699,19 @@ config ATAGS_PROC
          Should the atags used to boot the kernel be exported in an "atags"
          file in procfs. Useful with kexec.
 
+config CRASH_DUMP
+       bool "Build kdump crash kernel (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       help
+         Generate crash dump after being started by kexec. This should
+         be normally only set in special crash dump kernels which are
+         loaded in the main kernel with kexec-tools into a specially
+         reserved region and then later executed after a crash by
+         kdump/kexec. The crash dump kernel must be compiled to a
+         memory address not used by the main kernel
+
+         For more details see Documentation/kdump/kdump.txt
+
 config AUTO_ZRELADDR
        bool "Auto calculation of the decompressed kernel image address"
        depends on !ZBOOT_ROM && !ARCH_U300
@@ -1721,7 +1769,7 @@ config CPU_FREQ_S3C
          Internal configuration node for common cpufreq on Samsung SoC
 
 config CPU_FREQ_S3C24XX
-       bool "CPUfreq driver for Samsung S3C24XX series CPUs"
+       bool "CPUfreq driver for Samsung S3C24XX series CPUs (EXPERIMENTAL)"
        depends on ARCH_S3C2410 && CPU_FREQ && EXPERIMENTAL
        select CPU_FREQ_S3C
        help
@@ -1733,7 +1781,7 @@ config CPU_FREQ_S3C24XX
          If in doubt, say N.
 
 config CPU_FREQ_S3C24XX_PLL
-       bool "Support CPUfreq changing of PLL frequency"
+       bool "Support CPUfreq changing of PLL frequency (EXPERIMENTAL)"
        depends on CPU_FREQ_S3C24XX && EXPERIMENTAL
        help
          Compile in support for changing the PLL frequency from the
index eac62085f5b2add52908abe350990854caf8a5b2..494224a9b459060f94f39aafeeae8389111d50a0 100644 (file)
@@ -31,7 +31,7 @@ config FRAME_POINTER
          reported is severely limited.
 
 config ARM_UNWIND
-       bool "Enable stack unwinding support"
+       bool "Enable stack unwinding support (EXPERIMENTAL)"
        depends on AEABI && EXPERIMENTAL
        default y
        help
index 65a7c1c588a94ab4623be0ddfe02a691fb2954c6..0a8f748e506adfc415b857bc94dec36e25498999 100644 (file)
@@ -45,6 +45,10 @@ else
 endif
 endif
 
+ifeq ($(CONFIG_ARCH_SHMOBILE),y)
+OBJS           += head-shmobile.o
+endif
+
 #
 # We now have a PIC decompressor implementation.  Decompressors running
 # from RAM should not define ZTEXTADDR.  Decompressors running directly
diff --git a/arch/arm/boot/compressed/head-shmobile.S b/arch/arm/boot/compressed/head-shmobile.S
new file mode 100644 (file)
index 0000000..30973b7
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * The head-file for SH-Mobile ARM platforms
+ *
+ * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+ * Simon Horman <horms@verge.net.au>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ */
+
+#ifdef CONFIG_ZBOOT_ROM
+
+       .section        ".start", "ax"
+
+       /* load board-specific initialization code */
+#include <mach/zboot.h>
+
+       b       1f
+__atags:@ tag #1
+       .long   12                      @ tag->hdr.size = tag_size(tag_core);
+       .long   0x54410001              @ tag->hdr.tag = ATAG_CORE;
+       .long   0                       @ tag->u.core.flags = 0;
+       .long   0                       @ tag->u.core.pagesize = 0;
+       .long   0                       @ tag->u.core.rootdev = 0;
+       @ tag #2
+       .long   8                       @ tag->hdr.size = tag_size(tag_mem32);
+       .long   0x54410002              @ tag->hdr.tag = ATAG_MEM;
+       .long   CONFIG_MEMORY_SIZE      @ tag->u.mem.size = CONFIG_MEMORY_SIZE;
+       .long   CONFIG_MEMORY_START     @ @ tag->u.mem.start = CONFIG_MEMORY_START;
+       @ tag #3
+       .long   0                       @ tag->hdr.size = 0
+       .long   0                       @ tag->hdr.tag = ATAG_NONE;
+1:
+
+       /* Set board ID necessary for boot */
+       ldr     r7, 1f                          @ Set machine type register
+       adr     r8, __atags                     @ Set atag register
+       b       2f
+
+1 :    .long MACH_TYPE
+2 :
+
+#endif /* CONFIG_ZBOOT_ROM */
index 0a34c8186924415398601d46d488a2b011136219..778655f0257a9f27f73d3c1a0fddd81eb28919f4 100644 (file)
@@ -37,7 +37,3 @@ config SHARP_PARAM
 
 config SHARP_SCOOP
        bool
-
-config COMMON_CLKDEV
-       bool
-       select HAVE_CLK
index e6e8664a94139cd7e4086020d537ded4ca087f9e..e7521bca2c3564eaf3d21663fbf4ae3721e43461 100644 (file)
@@ -17,3 +17,4 @@ obj-$(CONFIG_ARCH_IXP2000)    += uengine.o
 obj-$(CONFIG_ARCH_IXP23XX)     += uengine.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
 obj-$(CONFIG_COMMON_CLKDEV)    += clkdev.o
+obj-$(CONFIG_ARM_TIMER_SP804)  += timer-sp.o
index cc0a932bbea90780f659becc4ee7d93087ab61cf..e5681636626f5fab71e38ac758a4409b2a127247 100644 (file)
@@ -328,7 +328,7 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
  * substitute the safe buffer for the unsafe one.
  * (basically move the buffer from an unsafe area to a safe one)
  */
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -338,7 +338,7 @@ dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 
        return map_single(dev, ptr, size, dir);
 }
-EXPORT_SYMBOL(dma_map_single);
+EXPORT_SYMBOL(__dma_map_single);
 
 /*
  * see if a mapped address was really a "safe" buffer and if so, copy
@@ -346,7 +346,7 @@ EXPORT_SYMBOL(dma_map_single);
  * the safe buffer.  (basically return things back to the way they
  * should be)
  */
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -354,9 +354,9 @@ void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 
        unmap_single(dev, dma_addr, size, dir);
 }
-EXPORT_SYMBOL(dma_unmap_single);
+EXPORT_SYMBOL(__dma_unmap_single);
 
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
+dma_addr_t __dma_map_page(struct device *dev, struct page *page,
                unsigned long offset, size_t size, enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
@@ -372,7 +372,7 @@ dma_addr_t dma_map_page(struct device *dev, struct page *page,
 
        return map_single(dev, page_address(page) + offset, size, dir);
 }
-EXPORT_SYMBOL(dma_map_page);
+EXPORT_SYMBOL(__dma_map_page);
 
 /*
  * see if a mapped address was really a "safe" buffer and if so, copy
@@ -380,7 +380,7 @@ EXPORT_SYMBOL(dma_map_page);
  * the safe buffer.  (basically return things back to the way they
  * should be)
  */
-void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
@@ -388,7 +388,7 @@ void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
 
        unmap_single(dev, dma_addr, size, dir);
 }
-EXPORT_SYMBOL(dma_unmap_page);
+EXPORT_SYMBOL(__dma_unmap_page);
 
 int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
                unsigned long off, size_t sz, enum dma_data_direction dir)
index e6388dcd8cfa2cf5f7a31ee59a6728bda377f89c..0b89ef001330d5f7ef0f256a4081cac0fc47a396 100644 (file)
@@ -35,6 +35,9 @@
 
 static DEFINE_SPINLOCK(irq_controller_lock);
 
+/* Address of GIC 0 CPU interface */
+void __iomem *gic_cpu_base_addr __read_mostly;
+
 struct gic_chip_data {
        unsigned int irq_offset;
        void __iomem *dist_base;
@@ -45,7 +48,7 @@ struct gic_chip_data {
 #define MAX_GIC_NR     1
 #endif
 
-static struct gic_chip_data gic_data[MAX_GIC_NR];
+static struct gic_chip_data gic_data[MAX_GIC_NR] __read_mostly;
 
 static inline void __iomem *gic_dist_base(unsigned int irq)
 {
@@ -213,21 +216,16 @@ void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
        set_irq_chained_handler(irq, gic_handle_cascade_irq);
 }
 
-void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
-                         unsigned int irq_start)
+static void __init gic_dist_init(struct gic_chip_data *gic,
+       unsigned int irq_start)
 {
        unsigned int gic_irqs, irq_limit, i;
+       void __iomem *base = gic->dist_base;
        u32 cpumask = 1 << smp_processor_id();
 
-       if (gic_nr >= MAX_GIC_NR)
-               BUG();
-
        cpumask |= cpumask << 8;
        cpumask |= cpumask << 16;
 
-       gic_data[gic_nr].dist_base = base;
-       gic_data[gic_nr].irq_offset = (irq_start - 1) & ~31;
-
        writel(0, base + GIC_DIST_CTRL);
 
        /*
@@ -267,7 +265,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
        /*
         * Limit number of interrupts registered to the platform maximum
         */
-       irq_limit = gic_data[gic_nr].irq_offset + gic_irqs;
+       irq_limit = gic->irq_offset + gic_irqs;
        if (WARN_ON(irq_limit > NR_IRQS))
                irq_limit = NR_IRQS;
 
@@ -276,7 +274,7 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
         */
        for (i = irq_start; i < irq_limit; i++) {
                set_irq_chip(i, &gic_chip);
-               set_irq_chip_data(i, &gic_data[gic_nr]);
+               set_irq_chip_data(i, gic);
                set_irq_handler(i, handle_level_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
@@ -284,19 +282,12 @@ void __init gic_dist_init(unsigned int gic_nr, void __iomem *base,
        writel(1, base + GIC_DIST_CTRL);
 }
 
-void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
+static void __cpuinit gic_cpu_init(struct gic_chip_data *gic)
 {
-       void __iomem *dist_base;
+       void __iomem *dist_base = gic->dist_base;
+       void __iomem *base = gic->cpu_base;
        int i;
 
-       if (gic_nr >= MAX_GIC_NR)
-               BUG();
-
-       dist_base = gic_data[gic_nr].dist_base;
-       BUG_ON(!dist_base);
-
-       gic_data[gic_nr].cpu_base = base;
-
        /*
         * Deal with the banked PPI and SGI interrupts - disable all
         * PPI interrupts, ensure all SGI interrupts are enabled.
@@ -314,6 +305,42 @@ void __cpuinit gic_cpu_init(unsigned int gic_nr, void __iomem *base)
        writel(1, base + GIC_CPU_CTRL);
 }
 
+void __init gic_init(unsigned int gic_nr, unsigned int irq_start,
+       void __iomem *dist_base, void __iomem *cpu_base)
+{
+       struct gic_chip_data *gic;
+
+       BUG_ON(gic_nr >= MAX_GIC_NR);
+
+       gic = &gic_data[gic_nr];
+       gic->dist_base = dist_base;
+       gic->cpu_base = cpu_base;
+       gic->irq_offset = (irq_start - 1) & ~31;
+
+       if (gic_nr == 0)
+               gic_cpu_base_addr = cpu_base;
+
+       gic_dist_init(gic, irq_start);
+       gic_cpu_init(gic);
+}
+
+void __cpuinit gic_secondary_init(unsigned int gic_nr)
+{
+       BUG_ON(gic_nr >= MAX_GIC_NR);
+
+       gic_cpu_init(&gic_data[gic_nr]);
+}
+
+void __cpuinit gic_enable_ppi(unsigned int irq)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       irq_to_desc(irq)->status |= IRQ_NOPROBE;
+       gic_unmask_irq(irq);
+       local_irq_restore(flags);
+}
+
 #ifdef CONFIG_SMP
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
index 1bec96e851967101df7a796745b84d24bd320ab8..42ff90b46dfb1f1e0e91fdfe370f493e0b81551f 100644 (file)
@@ -352,3 +352,4 @@ struct pci_bus * __init it8152_pci_scan_bus(int nr, struct pci_sys_data *sys)
        return pci_scan_bus(nr, &it8152_ops, sys);
 }
 
+EXPORT_SYMBOL(dma_set_coherent_mask);
similarity index 95%
rename from arch/arm/plat-versatile/timer-sp.c
rename to arch/arm/common/timer-sp.c
index fb0d1c299718c1537ca27a88da17b5439bf8b21d..6ef3342153b90c003d43a12123eee18560efffc7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/plat-versatile/timer-sp.c
+ *  linux/arch/arm/common/timer-sp.c
  *
  *  Copyright (C) 1999 - 2003 ARM Limited
  *  Copyright (C) 2000 Deep Blue Solutions Ltd
@@ -26,8 +26,6 @@
 
 #include <asm/hardware/arm_timer.h>
 
-#include <plat/timer-sp.h>
-
 /*
  * These timers are currently always setup to be clocked at 1MHz.
  */
@@ -46,7 +44,6 @@ static struct clocksource clocksource_sp804 = {
        .rating         = 200,
        .read           = sp804_read,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -63,8 +60,7 @@ void __init sp804_clocksource_init(void __iomem *base)
        writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
                clksrc_base + TIMER_CTRL);
 
-       cs->mult = clocksource_khz2mult(TIMER_FREQ_KHZ, cs->shift);
-       clocksource_register(cs);
+       clocksource_register_khz(cs, TIMER_FREQ_KHZ);
 }
 
 
index 749bb6622404b3aed8e9234d2c8ff67e13a731b1..bc2d2d75f7068998bb69a92b69c1216ec4dbd8fe 100644 (file)
@@ -18,6 +18,7 @@
 #endif
 
 #include <asm/ptrace.h>
+#include <asm/domain.h>
 
 /*
  * Endian independent macros for shifting bytes within registers.
 #ifdef CONFIG_SMP
 #define ALT_SMP(instr...)                                      \
 9998:  instr
+/*
+ * Note: if you get assembler errors from ALT_UP() when building with
+ * CONFIG_THUMB2_KERNEL, you almost certainly need to use
+ * ALT_SMP( W(instr) ... )
+ */
 #define ALT_UP(instr...)                                       \
        .pushsection ".alt.smp.init", "a"                       ;\
        .long   9998b                                           ;\
-       instr                                                   ;\
+9997:  instr                                                   ;\
+       .if . - 9997b != 4                                      ;\
+               .error "ALT_UP() content must assemble to exactly 4 bytes";\
+       .endif                                                  ;\
        .popsection
 #define ALT_UP_B(label)                                        \
        .equ    up_b_offset, label - 9998b                      ;\
        .pushsection ".alt.smp.init", "a"                       ;\
        .long   9998b                                           ;\
-       b       . + up_b_offset                                 ;\
+       W(b)    . + up_b_offset                                 ;\
        .popsection
 #else
 #define ALT_SMP(instr...)
 /*
  * SMP data memory barrier
  */
-       .macro  smp_dmb
+       .macro  smp_dmb mode
 #ifdef CONFIG_SMP
 #if __LINUX_ARM_ARCH__ >= 7
+       .ifeqs "\mode","arm"
        ALT_SMP(dmb)
+       .else
+       ALT_SMP(W(dmb))
+       .endif
 #elif __LINUX_ARM_ARCH__ == 6
        ALT_SMP(mcr     p15, 0, r0, c7, c10, 5) @ dmb
 #else
 #error Incompatible SMP platform
 #endif
+       .ifeqs "\mode","arm"
        ALT_UP(nop)
+       .else
+       ALT_UP(W(nop))
+       .endif
 #endif
        .endm
 
  */
 #ifdef CONFIG_THUMB2_KERNEL
 
-       .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort
+       .macro  usraccoff, instr, reg, ptr, inc, off, cond, abort, t=T()
 9999:
        .if     \inc == 1
-       \instr\cond\()bt \reg, [\ptr, #\off]
+       \instr\cond\()b\()\t\().w \reg, [\ptr, #\off]
        .elseif \inc == 4
-       \instr\cond\()t \reg, [\ptr, #\off]
+       \instr\cond\()\t\().w \reg, [\ptr, #\off]
        .else
        .error  "Unsupported inc macro argument"
        .endif
 
 #else  /* !CONFIG_THUMB2_KERNEL */
 
-       .macro  usracc, instr, reg, ptr, inc, cond, rept, abort
+       .macro  usracc, instr, reg, ptr, inc, cond, rept, abort, t=T()
        .rept   \rept
 9999:
        .if     \inc == 1
-       \instr\cond\()bt \reg, [\ptr], #\inc
+       \instr\cond\()b\()\t \reg, [\ptr], #\inc
        .elseif \inc == 4
-       \instr\cond\()t \reg, [\ptr], #\inc
+       \instr\cond\()\t \reg, [\ptr], #\inc
        .else
        .error  "Unsupported inc macro argument"
        .endif
index 9d6122096fbec40ad41ab473c189722816225399..75fe66bc02b420014f37459c1ad786d49b1529c0 100644 (file)
@@ -23,4 +23,6 @@
 #define ARCH_SLAB_MINALIGN 8
 #endif
 
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
+
 #endif
index b56c1389b6fa49da16bb940a04931480a4466c84..765d3322236942473fb342ad49a32746200f6bc3 100644 (file)
 #ifndef __ASM_CLKDEV_H
 #define __ASM_CLKDEV_H
 
-struct clk;
-struct device;
+#include <linux/slab.h>
 
-struct clk_lookup {
-       struct list_head        node;
-       const char              *dev_id;
-       const char              *con_id;
-       struct clk              *clk;
-};
+#include <mach/clkdev.h>
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-       const char *dev_fmt, ...);
-
-void clkdev_add(struct clk_lookup *cl);
-void clkdev_drop(struct clk_lookup *cl);
-
-void clkdev_add_table(struct clk_lookup *, size_t);
-int clk_add_alias(const char *, const char *, char *, struct device *);
+static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
+{
+       return kzalloc(size, GFP_KERNEL);
+}
 
 #endif
index c568da7dcae45e60e8630e2b3060599f561d6555..4fff837363edd93249a0884d11f0fabc2ec6db30 100644 (file)
@@ -5,24 +5,29 @@
 
 #include <linux/mm_types.h>
 #include <linux/scatterlist.h>
+#include <linux/dma-debug.h>
 
 #include <asm-generic/dma-coherent.h>
 #include <asm/memory.h>
 
+#ifdef __arch_page_to_dma
+#error Please update to __arch_pfn_to_dma
+#endif
+
 /*
- * page_to_dma/dma_to_virt/virt_to_dma are architecture private functions
- * used internally by the DMA-mapping API to provide DMA addresses. They
- * must not be used by drivers.
+ * dma_to_pfn/pfn_to_dma/dma_to_virt/virt_to_dma are architecture private
+ * functions used internally by the DMA-mapping API to provide DMA
+ * addresses. They must not be used by drivers.
  */
-#ifndef __arch_page_to_dma
-static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
+#ifndef __arch_pfn_to_dma
+static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
-       return (dma_addr_t)__pfn_to_bus(page_to_pfn(page));
+       return (dma_addr_t)__pfn_to_bus(pfn);
 }
 
-static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr)
+static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-       return pfn_to_page(__bus_to_pfn(addr));
+       return __bus_to_pfn(addr);
 }
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
@@ -35,14 +40,14 @@ static inline dma_addr_t virt_to_dma(struct device *dev, void *addr)
        return (dma_addr_t)__virt_to_bus((unsigned long)(addr));
 }
 #else
-static inline dma_addr_t page_to_dma(struct device *dev, struct page *page)
+static inline dma_addr_t pfn_to_dma(struct device *dev, unsigned long pfn)
 {
-       return __arch_page_to_dma(dev, page);
+       return __arch_pfn_to_dma(dev, pfn);
 }
 
-static inline struct page *dma_to_page(struct device *dev, dma_addr_t addr)
+static inline unsigned long dma_to_pfn(struct device *dev, dma_addr_t addr)
 {
-       return __arch_dma_to_page(dev, addr);
+       return __arch_dma_to_pfn(dev, addr);
 }
 
 static inline void *dma_to_virt(struct device *dev, dma_addr_t addr)
@@ -293,13 +298,13 @@ extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
 /*
  * The DMA API, implemented by dmabounce.c.  See below for descriptions.
  */
-extern dma_addr_t dma_map_single(struct device *, void *, size_t,
+extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
                enum dma_data_direction);
-extern void dma_unmap_single(struct device *, dma_addr_t, size_t,
+extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
                enum dma_data_direction);
-extern dma_addr_t dma_map_page(struct device *, struct page *,
+extern dma_addr_t __dma_map_page(struct device *, struct page *,
                unsigned long, size_t, enum dma_data_direction);
-extern void dma_unmap_page(struct device *, dma_addr_t, size_t,
+extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
                enum dma_data_direction);
 
 /*
@@ -323,6 +328,34 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
 }
 
 
+static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_single_cpu_to_dev(cpu_addr, size, dir);
+       return virt_to_dma(dev, cpu_addr);
+}
+
+static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
+            unsigned long offset, size_t size, enum dma_data_direction dir)
+{
+       __dma_page_cpu_to_dev(page, offset, size, dir);
+       return pfn_to_dma(dev, page_to_pfn(page)) + offset;
+}
+
+static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+}
+
+static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
+               handle & ~PAGE_MASK, size, dir);
+}
+#endif /* CONFIG_DMABOUNCE */
+
 /**
  * dma_map_single - map a single buffer for streaming DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
@@ -340,11 +373,16 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
 static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
                size_t size, enum dma_data_direction dir)
 {
+       dma_addr_t addr;
+
        BUG_ON(!valid_dma_direction(dir));
 
-       __dma_single_cpu_to_dev(cpu_addr, size, dir);
+       addr = __dma_map_single(dev, cpu_addr, size, dir);
+       debug_dma_map_page(dev, virt_to_page(cpu_addr),
+                       (unsigned long)cpu_addr & ~PAGE_MASK, size,
+                       dir, addr, true);
 
-       return virt_to_dma(dev, cpu_addr);
+       return addr;
 }
 
 /**
@@ -364,11 +402,14 @@ static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
 static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir)
 {
+       dma_addr_t addr;
+
        BUG_ON(!valid_dma_direction(dir));
 
-       __dma_page_cpu_to_dev(page, offset, size, dir);
+       addr = __dma_map_page(dev, page, offset, size, dir);
+       debug_dma_map_page(dev, page, offset, size, dir, addr, false);
 
-       return page_to_dma(dev, page) + offset;
+       return addr;
 }
 
 /**
@@ -388,7 +429,8 @@ static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
 static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir)
 {
-       __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+       debug_dma_unmap_page(dev, handle, size, dir, true);
+       __dma_unmap_single(dev, handle, size, dir);
 }
 
 /**
@@ -408,10 +450,9 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
 static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir)
 {
-       __dma_page_dev_to_cpu(dma_to_page(dev, handle), handle & ~PAGE_MASK,
-               size, dir);
+       debug_dma_unmap_page(dev, handle, size, dir, false);
+       __dma_unmap_page(dev, handle, size, dir);
 }
-#endif /* CONFIG_DMABOUNCE */
 
 /**
  * dma_sync_single_range_for_cpu
@@ -437,6 +478,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
 {
        BUG_ON(!valid_dma_direction(dir));
 
+       debug_dma_sync_single_for_cpu(dev, handle + offset, size, dir);
+
        if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
                return;
 
@@ -449,6 +492,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
 {
        BUG_ON(!valid_dma_direction(dir));
 
+       debug_dma_sync_single_for_device(dev, handle + offset, size, dir);
+
        if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
                return;
 
index cc7ef4080711ff5b2b506449dc54602d8fe65b8d..af18ceaacf5d2ec2bafe51de722387fb3249ac4e 100644 (file)
  */
 #define DOMAIN_NOACCESS        0
 #define DOMAIN_CLIENT  1
+#ifdef CONFIG_CPU_USE_DOMAINS
 #define DOMAIN_MANAGER 3
+#else
+#define DOMAIN_MANAGER 1
+#endif
 
 #define domain_val(dom,type)   ((type) << (2*(dom)))
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
 #define set_domain(x)                                  \
        do {                                            \
        __asm__ __volatile__(                           \
 #define modify_domain(dom,type)        do { } while (0)
 #endif
 
+/*
+ * Generate the T (user) versions of the LDR/STR and related
+ * instructions (inline assembly)
+ */
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define T(instr)       #instr "t"
+#else
+#define T(instr)       #instr
 #endif
-#endif /* !__ASSEMBLY__ */
+
+#else /* __ASSEMBLY__ */
+
+/*
+ * Generate the T (user) versions of the LDR/STR and related
+ * instructions
+ */
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define T(instr)       instr ## t
+#else
+#define T(instr)       instr
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* !__ASM_PROC_DOMAIN_H */
index 8bb66bca2e3eb8a8561f2c63d9334e8991ebb728..c3cd8755e64897d49938c8b454dafec18c0ebffc 100644 (file)
@@ -99,6 +99,8 @@ struct elf32_hdr;
 extern int elf_check_arch(const struct elf32_hdr *);
 #define elf_check_arch elf_check_arch
 
+#define vmcore_elf64_check_arch(x) (0)
+
 extern int arm_elf_read_implies_exec(const struct elf32_hdr *, int);
 #define elf_read_implies_exec(ex,stk) arm_elf_read_implies_exec(&(ex), stk)
 
diff --git a/arch/arm/include/asm/entry-macro-multi.S b/arch/arm/include/asm/entry-macro-multi.S
new file mode 100644 (file)
index 0000000..ec0bbf7
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Interrupt handling.  Preserves r7, r8, r9
+ */
+       .macro  arch_irq_handler_default
+       get_irqnr_preamble r5, lr
+1:     get_irqnr_and_base r0, r6, r5, lr
+       movne   r1, sp
+       @
+       @ routine called with r0 = irq number, r1 = struct pt_regs *
+       @
+       adrne   lr, BSYM(1b)
+       bne     asm_do_IRQ
+
+#ifdef CONFIG_SMP
+       /*
+        * XXX
+        *
+        * this macro assumes that irqstat (r6) and base (r5) are
+        * preserved from get_irqnr_and_base above
+        */
+       ALT_SMP(test_for_ipi r0, r6, r5, lr)
+       ALT_UP_B(9997f)
+       movne   r1, sp
+       adrne   lr, BSYM(1b)
+       bne     do_IPI
+
+#ifdef CONFIG_LOCAL_TIMERS
+       test_for_ltirq r0, r6, r5, lr
+       movne   r0, sp
+       adrne   lr, BSYM(1b)
+       bne     do_local_timer
+#endif
+#endif
+9997:
+       .endm
+
+       .macro  arch_irq_handler, symbol_name
+       .align  5
+       .global \symbol_name
+\symbol_name:
+       mov     r4, lr
+       arch_irq_handler_default
+       mov     pc, r4
+       .endm
index 540a044153a54ce1ffc8bed90a6bf7cee59631d8..b33fe7065b38694fa1d3047c6147a74348d4b732 100644 (file)
 #include <linux/preempt.h>
 #include <linux/uaccess.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg)     \
        __asm__ __volatile__(                                   \
-       "1:     ldrt    %1, [%2]\n"                             \
+       "1:     " T(ldr) "      %1, [%2]\n"                     \
        "       " insn "\n"                                     \
-       "2:     strt    %0, [%2]\n"                             \
+       "2:     " T(str) "      %0, [%2]\n"                     \
        "       mov     %0, #0\n"                               \
        "3:\n"                                                  \
        "       .pushsection __ex_table,\"a\"\n"                \
@@ -97,10 +98,10 @@ futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
        pagefault_disable();    /* implies preempt_disable() */
 
        __asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-       "1:     ldrt    %0, [%3]\n"
+       "1:     " T(ldr) "      %0, [%3]\n"
        "       teq     %0, %1\n"
        "       it      eq      @ explicit IT needed for the 2b label\n"
-       "2:     streqt  %2, [%3]\n"
+       "2:     " T(streq) "    %2, [%3]\n"
        "3:\n"
        "       .pushsection __ex_table,\"a\"\n"
        "       .align  3\n"
index 6d7485aff9558dcfba7de1f1cfb4a648778a6c6b..89ad1805e5797625a2d5df0912253bcd9e2a9f5f 100644 (file)
@@ -5,13 +5,31 @@
 #include <linux/threads.h>
 #include <asm/irq.h>
 
+#define NR_IPI 5
+
 typedef struct {
        unsigned int __softirq_pending;
+#ifdef CONFIG_LOCAL_TIMERS
        unsigned int local_timer_irqs;
+#endif
+#ifdef CONFIG_SMP
+       unsigned int ipi_irqs[NR_IPI];
+#endif
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
 
+#define __inc_irq_stat(cpu, member)    __IRQ_STAT(cpu, member)++
+#define __get_irq_stat(cpu, member)    __IRQ_STAT(cpu, member)
+
+#ifdef CONFIG_SMP
+u64 smp_irq_stat_cpu(unsigned int cpu);
+#else
+#define smp_irq_stat_cpu(cpu)  0
+#endif
+
+#define arch_irq_stat_cpu      smp_irq_stat_cpu
+
 #if NR_IRQS > 512
 #define HARDIRQ_BITS   10
 #elif NR_IRQS > 256
diff --git a/arch/arm/include/asm/hardware/entry-macro-gic.S b/arch/arm/include/asm/hardware/entry-macro-gic.S
new file mode 100644 (file)
index 0000000..c115b82
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * arch/arm/include/asm/hardware/entry-macro-gic.S
+ *
+ * Low-level IRQ helper macros for GIC
+ *
+ * This file is licensed under  the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <asm/hardware/gic.h>
+
+#ifndef HAVE_GET_IRQNR_PREAMBLE
+       .macro  get_irqnr_preamble, base, tmp
+       ldr     \base, =gic_cpu_base_addr
+       ldr     \base, [\base]
+       .endm
+#endif
+
+/*
+ * The interrupt numbering scheme is defined in the
+ * interrupt controller spec.  To wit:
+ *
+ * Interrupts 0-15 are IPI
+ * 16-28 are reserved
+ * 29-31 are local.  We allow 30 to be used for the watchdog.
+ * 32-1020 are global
+ * 1021-1022 are reserved
+ * 1023 is "spurious" (no interrupt)
+ *
+ * For now, we ignore all local interrupts so only return an interrupt if it's
+ * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
+ *
+ * A simple read from the controller will tell us the number of the highest
+ * priority enabled interrupt.  We then just need to check whether it is in the
+ * valid range for an IRQ (30-1020 inclusive).
+ */
+
+       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
+
+       ldr     \irqstat, [\base, #GIC_CPU_INTACK]
+       /* bits 12-10 = src CPU, 9-0 = int # */
+
+       ldr     \tmp, =1021
+       bic     \irqnr, \irqstat, #0x1c00
+       cmp     \irqnr, #29
+       cmpcc   \irqnr, \irqnr
+       cmpne   \irqnr, \tmp
+       cmpcs   \irqnr, \irqnr
+       .endm
+
+/* We assume that irqstat (the raw value of the IRQ acknowledge
+ * register) is preserved from the macro above.
+ * If there is an IPI, we immediately signal end of interrupt on the
+ * controller, since this requires the original irqstat value which
+ * we won't easily be able to recreate later.
+ */
+
+       .macro test_for_ipi, irqnr, irqstat, base, tmp
+       bic     \irqnr, \irqstat, #0x1c00
+       cmp     \irqnr, #16
+       strcc   \irqstat, [\base, #GIC_CPU_EOI]
+       cmpcs   \irqnr, \irqnr
+       .endm
+
+/* As above, this assumes that irqstat and base are preserved.. */
+
+       .macro test_for_ltirq, irqnr, irqstat, base, tmp
+       bic     \irqnr, \irqstat, #0x1c00
+       mov     \tmp, #0
+       cmp     \irqnr, #29
+       moveq   \tmp, #1
+       streq   \irqstat, [\base, #GIC_CPU_EOI]
+       cmp     \tmp, #0
+       .endm
index 7f34333bb5455db6093e85f99ea3a8dd7d6d5fef..84557d321001396e62ca8949f126be0db2a1fcb1 100644 (file)
 #define GIC_DIST_SOFTINT               0xf00
 
 #ifndef __ASSEMBLY__
-void gic_dist_init(unsigned int gic_nr, void __iomem *base, unsigned int irq_start);
-void gic_cpu_init(unsigned int gic_nr, void __iomem *base);
+extern void __iomem *gic_cpu_base_addr;
+
+void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
+void gic_secondary_init(unsigned int);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
 void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
+void gic_enable_ppi(unsigned int);
 #endif
 
 #endif
index 21fa272301f804b9bad3218b74147f6e450fa026..b2f95c72287c861dc03c09e110242982bb51a5c5 100644 (file)
@@ -76,6 +76,7 @@ extern unsigned long it8152_base_address;
   IT8152_PD_IRQ(0)  Audio controller (ACR)
  */
 #define IT8152_IRQ(x)   (IRQ_BOARD_START + (x))
+#define IT8152_LAST_IRQ        (IRQ_BOARD_START + 40)
 
 /* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
 #define IT8152_LD_IRQ_COUNT     9
index 1fc684e70ab6a6c9915ad5fbd302066ccb050a29..7080e2c8fa6209e0445b59a7b33ba8bd825797af 100644 (file)
@@ -25,9 +25,6 @@ extern void *kmap_high(struct page *page);
 extern void *kmap_high_get(struct page *page);
 extern void kunmap_high(struct page *page);
 
-extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte);
-extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte);
-
 /*
  * The following functions are already defined by <linux/highmem.h>
  * when CONFIG_HIGHMEM is not set.
index 815efa2d4e07b5087e31965a06fc05c1fdfd9fa0..20e0f7c9e03ed91678324170d8039ceadeea37a3 100644 (file)
@@ -241,18 +241,15 @@ extern void _memset_io(volatile void __iomem *, int, size_t);
  *
  */
 #ifndef __arch_ioremap
-#define ioremap(cookie,size)           __arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_nocache(cookie,size)   __arm_ioremap(cookie, size, MT_DEVICE)
-#define ioremap_cached(cookie,size)    __arm_ioremap(cookie, size, MT_DEVICE_CACHED)
-#define ioremap_wc(cookie,size)                __arm_ioremap(cookie, size, MT_DEVICE_WC)
-#define iounmap(cookie)                        __iounmap(cookie)
-#else
+#define __arch_ioremap                 __arm_ioremap
+#define __arch_iounmap                 __iounmap
+#endif
+
 #define ioremap(cookie,size)           __arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_nocache(cookie,size)   __arch_ioremap((cookie), (size), MT_DEVICE)
 #define ioremap_cached(cookie,size)    __arch_ioremap((cookie), (size), MT_DEVICE_CACHED)
 #define ioremap_wc(cookie,size)                __arch_ioremap((cookie), (size), MT_DEVICE_WC)
-#define iounmap(cookie)                        __arch_iounmap(cookie)
-#endif
+#define iounmap                                __arch_iounmap
 
 /*
  * io{read,write}{8,16,32} macros
index 8ec9ef5c3c7be25a2705451e8aab0a8205a47e67..c0094d8edae45c1d331b0ec6a63a0105ee8a109a 100644 (file)
@@ -33,10 +33,20 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
        if (oldregs) {
                memcpy(newregs, oldregs, sizeof(*newregs));
        } else {
-               __asm__ __volatile__ ("stmia %0, {r0 - r15}"
-                                     : : "r" (&newregs->ARM_r0));
-               __asm__ __volatile__ ("mrs %0, cpsr"
-                                     : "=r" (newregs->ARM_cpsr));
+               __asm__ __volatile__ (
+                       "stmia  %[regs_base], {r0-r12}\n\t"
+                       "mov    %[_ARM_sp], sp\n\t"
+                       "str    lr, %[_ARM_lr]\n\t"
+                       "adr    %[_ARM_pc], 1f\n\t"
+                       "mrs    %[_ARM_cpsr], cpsr\n\t"
+               "1:"
+                       : [_ARM_pc] "=r" (newregs->ARM_pc),
+                         [_ARM_cpsr] "=r" (newregs->ARM_cpsr),
+                         [_ARM_sp] "=r" (newregs->ARM_sp),
+                         [_ARM_lr] "=o" (newregs->ARM_lr)
+                       : [regs_base] "r" (&newregs->ARM_r0)
+                       : "memory"
+               );
        }
 }
 
index 50c7e7cfd670792b476a50f3fc64fcdc1188f6fb..6bc63ab498ce45d3c343a4b51f4b26790c8640ee 100644 (file)
@@ -30,7 +30,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
 #include "smp_twd.h"
 
 #define local_timer_ack()      twd_timer_ack()
-#define local_timer_stop()     twd_timer_stop()
 
 #else
 
@@ -40,11 +39,6 @@ asmlinkage void do_local_timer(struct pt_regs *);
  */
 int local_timer_ack(void);
 
-/*
- * Stop a local timer interrupt.
- */
-void local_timer_stop(void);
-
 #endif
 
 /*
@@ -52,12 +46,6 @@ void local_timer_stop(void);
  */
 void local_timer_setup(struct clock_event_device *);
 
-#else
-
-static inline void local_timer_stop(void)
-{
-}
-
 #endif
 
 #endif
index d97a964207fa15693c011f88f27dc64f4c7c3f16..3a0893a76a3b23abbb8ecaf4c4c9ce1a528f3bd4 100644 (file)
@@ -37,11 +37,20 @@ struct machine_desc {
                                         struct meminfo *);
        void                    (*reserve)(void);/* reserve mem blocks  */
        void                    (*map_io)(void);/* IO mapping function  */
+       void                    (*init_early)(void);
        void                    (*init_irq)(void);
        struct sys_timer        *timer;         /* system tick timer    */
        void                    (*init_machine)(void);
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+       void                    (*handle_irq)(struct pt_regs *);
+#endif
 };
 
+/*
+ * Current machine - only accessible during boot.
+ */
+extern struct machine_desc *machine_desc;
+
 /*
  * Set of macros to define architecture features.  This is built into
  * a table by the linker.
index ce3eee9fe26cbb055cbea6ab0d5567af4964b29a..22ac140edd9efb83ee2b770636d6ef32e7916f1e 100644 (file)
@@ -17,10 +17,12 @@ struct seq_file;
 /*
  * This is internal.  Do not use it.
  */
-extern unsigned int arch_nr_irqs;
-extern void (*init_arch_irq)(void);
 extern void init_FIQ(void);
-extern int show_fiq_list(struct seq_file *, void *);
+extern int show_fiq_list(struct seq_file *, int);
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+extern void (*handle_arch_irq)(struct pt_regs *);
+#endif
 
 /*
  * This is for easy migration, but should be changed in the source
index 35d408f6dccfbee8db3b678576166af283f8ed56..883f6be5117a75a529e8a07af892cc80f2974dd6 100644 (file)
@@ -43,7 +43,6 @@ struct sys_timer {
 #endif
 };
 
-extern struct sys_timer *system_timer;
 extern void timer_tick(void);
 
 #endif
index cbb0bc295d2b184d380e63920dcb55930c7b76b7..12c8e680cbff777dbac6fe992eb4ddac60017913 100644 (file)
@@ -8,11 +8,6 @@
 struct unwind_table;
 
 #ifdef CONFIG_ARM_UNWIND
-struct arm_unwind_mapping {
-       Elf_Shdr *unw_sec;
-       Elf_Shdr *sec_text;
-       struct unwind_table *unwind;
-};
 enum {
        ARM_SEC_INIT,
        ARM_SEC_DEVINIT,
@@ -21,13 +16,13 @@ enum {
        ARM_SEC_DEVEXIT,
        ARM_SEC_MAX,
 };
+#endif
+
 struct mod_arch_specific {
-       struct arm_unwind_mapping map[ARM_SEC_MAX];
-};
-#else
-struct mod_arch_specific {
-};
+#ifdef CONFIG_ARM_UNWIND
+       struct unwind_table *unwind[ARM_SEC_MAX];
 #endif
+};
 
 /*
  * Include the ARM architecture version.
index a485ac3c8696d2cdbc2e9a857ba4298de63e1428..f51a69595f6ed53bc2d46d07a146f8b08ac6b83d 100644 (file)
@@ -151,13 +151,15 @@ extern void __cpu_copy_user_highpage(struct page *to, struct page *from,
 #define clear_page(page)       memset((void *)(page), 0, PAGE_SIZE)
 extern void copy_page(void *to, const void *from);
 
+typedef unsigned long pteval_t;
+
 #undef STRICT_MM_TYPECHECKS
 
 #ifdef STRICT_MM_TYPECHECKS
 /*
  * These are used to make use of C type-checking..
  */
-typedef struct { unsigned long pte; } pte_t;
+typedef struct { pteval_t pte; } pte_t;
 typedef struct { unsigned long pmd; } pmd_t;
 typedef struct { unsigned long pgd[2]; } pgd_t;
 typedef struct { unsigned long pgprot; } pgprot_t;
@@ -175,7 +177,7 @@ typedef struct { unsigned long pgprot; } pgprot_t;
 /*
  * .. while these make it easier on the compiler
  */
-typedef unsigned long pte_t;
+typedef pteval_t pte_t;
 typedef unsigned long pmd_t;
 typedef unsigned long pgd_t[2];
 typedef unsigned long pgprot_t;
index b12cc98bbe044649e27ea683f73f1dbffd052072..9763be04f77ee9e15b8e759a1b392cb7f66b3b6f 100644 (file)
 #define pmd_free(mm, pmd)              do { } while (0)
 #define pgd_populate(mm,pmd,pte)       BUG()
 
-extern pgd_t *get_pgd_slow(struct mm_struct *mm);
-extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
-
-#define pgd_alloc(mm)                  get_pgd_slow(mm)
-#define pgd_free(mm, pgd)              free_pgd_slow(mm, pgd)
+extern pgd_t *pgd_alloc(struct mm_struct *mm);
+extern void pgd_free(struct mm_struct *mm, pgd_t *pgd);
 
 #define PGALLOC_GFP    (GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
 
+static inline void clean_pte_table(pte_t *pte)
+{
+       clean_dcache_area(pte + PTE_HWTABLE_PTRS, PTE_HWTABLE_SIZE);
+}
+
 /*
  * Allocate one PTE table.
  *
@@ -45,14 +47,14 @@ extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
  * into one table thus:
  *
  *  +------------+
- *  |  h/w pt 0  |
- *  +------------+
- *  |  h/w pt 1  |
- *  +------------+
  *  | Linux pt 0 |
  *  +------------+
  *  | Linux pt 1 |
  *  +------------+
+ *  |  h/w pt 0  |
+ *  +------------+
+ *  |  h/w pt 1  |
+ *  +------------+
  */
 static inline pte_t *
 pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
@@ -60,10 +62,8 @@ pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
        pte_t *pte;
 
        pte = (pte_t *)__get_free_page(PGALLOC_GFP);
-       if (pte) {
-               clean_dcache_area(pte, sizeof(pte_t) * PTRS_PER_PTE);
-               pte += PTRS_PER_PTE;
-       }
+       if (pte)
+               clean_pte_table(pte);
 
        return pte;
 }
@@ -79,10 +79,8 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr)
        pte = alloc_pages(PGALLOC_GFP, 0);
 #endif
        if (pte) {
-               if (!PageHighMem(pte)) {
-                       void *page = page_address(pte);
-                       clean_dcache_area(page, sizeof(pte_t) * PTRS_PER_PTE);
-               }
+               if (!PageHighMem(pte))
+                       clean_pte_table(page_address(pte));
                pgtable_page_ctor(pte);
        }
 
@@ -94,10 +92,8 @@ pte_alloc_one(struct mm_struct *mm, unsigned long addr)
  */
 static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
 {
-       if (pte) {
-               pte -= PTRS_PER_PTE;
+       if (pte)
                free_page((unsigned long)pte);
-       }
 }
 
 static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
@@ -106,8 +102,10 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
        __free_page(pte);
 }
 
-static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
+static inline void __pmd_populate(pmd_t *pmdp, phys_addr_t pte,
+       unsigned long prot)
 {
+       unsigned long pmdval = (pte + PTE_HWTABLE_OFF) | prot;
        pmdp[0] = __pmd(pmdval);
        pmdp[1] = __pmd(pmdval + 256 * sizeof(pte_t));
        flush_pmd_entry(pmdp);
@@ -122,20 +120,16 @@ static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
 static inline void
 pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
 {
-       unsigned long pte_ptr = (unsigned long)ptep;
-
        /*
-        * The pmd must be loaded with the physical
-        * address of the PTE table
+        * The pmd must be loaded with the physical address of the PTE table
         */
-       pte_ptr -= PTRS_PER_PTE * sizeof(void *);
-       __pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE);
+       __pmd_populate(pmdp, __pa(ptep), _PAGE_KERNEL_TABLE);
 }
 
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
 {
-       __pmd_populate(pmdp, page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
+       __pmd_populate(pmdp, page_to_phys(ptep), _PAGE_USER_TABLE);
 }
 #define pmd_pgtable(pmd) pmd_page(pmd)
 
index 53d1d5deb1115b1fe11a52846e62679573534d24..ebcb6432f45f829daaa0c33818b7347fe8df26c1 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef _ASMARM_PGTABLE_H
 #define _ASMARM_PGTABLE_H
 
+#include <linux/const.h>
 #include <asm-generic/4level-fixup.h>
 #include <asm/proc-fns.h>
 
@@ -54,7 +55,7 @@
  * Therefore, we tweak the implementation slightly - we tell Linux that we
  * have 2048 entries in the first level, each of which is 8 bytes (iow, two
  * hardware pointers to the second level.)  The second level contains two
- * hardware PTE tables arranged contiguously, followed by Linux versions
+ * hardware PTE tables arranged contiguously, preceded by Linux versions
  * which contain the state information Linux needs.  We, therefore, end up
  * with 512 entries in the "PTE" level.
  *
  *
  *    pgd             pte
  * |        |
- * +--------+ +0
- * |        |-----> +------------+ +0
+ * +--------+
+ * |        |       +------------+ +0
+ * +- - - - +       | Linux pt 0 |
+ * |        |       +------------+ +1024
+ * +--------+ +0    | Linux pt 1 |
+ * |        |-----> +------------+ +2048
  * +- - - - + +4    |  h/w pt 0  |
- * |        |-----> +------------+ +1024
+ * |        |-----> +------------+ +3072
  * +--------+ +8    |  h/w pt 1  |
- * |        |       +------------+ +2048
- * +- - - - +       | Linux pt 0 |
- * |        |       +------------+ +3072
- * +--------+       | Linux pt 1 |
  * |        |       +------------+ +4096
  *
  * See L_PTE_xxx below for definitions of bits in the "Linux pt", and
 #define PTRS_PER_PMD           1
 #define PTRS_PER_PGD           2048
 
+#define PTE_HWTABLE_PTRS       (PTRS_PER_PTE)
+#define PTE_HWTABLE_OFF                (PTE_HWTABLE_PTRS * sizeof(pte_t))
+#define PTE_HWTABLE_SIZE       (PTRS_PER_PTE * sizeof(u32))
+
 /*
  * PMD_SHIFT determines the size of the area a second-level page table can map
  * PGDIR_SHIFT determines what a third-level page table entry can map
 #define LIBRARY_TEXT_START     0x0c000000
 
 #ifndef __ASSEMBLY__
-extern void __pte_error(const char *file, int line, unsigned long val);
-extern void __pmd_error(const char *file, int line, unsigned long val);
-extern void __pgd_error(const char *file, int line, unsigned long val);
+extern void __pte_error(const char *file, int line, pte_t);
+extern void __pmd_error(const char *file, int line, pmd_t);
+extern void __pgd_error(const char *file, int line, pgd_t);
 
-#define pte_ERROR(pte)         __pte_error(__FILE__, __LINE__, pte_val(pte))
-#define pmd_ERROR(pmd)         __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
-#define pgd_ERROR(pgd)         __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+#define pte_ERROR(pte)         __pte_error(__FILE__, __LINE__, pte)
+#define pmd_ERROR(pmd)         __pmd_error(__FILE__, __LINE__, pmd)
+#define pgd_ERROR(pgd)         __pgd_error(__FILE__, __LINE__, pgd)
 #endif /* !__ASSEMBLY__ */
 
 #define PMD_SIZE               (1UL << PMD_SHIFT)
@@ -133,8 +138,7 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
  */
 #define FIRST_USER_ADDRESS     PAGE_SIZE
 
-#define FIRST_USER_PGD_NR      1
-#define USER_PTRS_PER_PGD      ((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
+#define USER_PTRS_PER_PGD      (TASK_SIZE / PGDIR_SIZE)
 
 /*
  * section address mask and size definitions.
@@ -161,30 +165,30 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
  * The PTE table pointer refers to the hardware entries; the "Linux"
  * entries are stored 1024 bytes below.
  */
-#define L_PTE_PRESENT          (1 << 0)
-#define L_PTE_YOUNG            (1 << 1)
-#define L_PTE_FILE             (1 << 2)        /* only when !PRESENT */
-#define L_PTE_DIRTY            (1 << 6)
-#define L_PTE_WRITE            (1 << 7)
-#define L_PTE_USER             (1 << 8)
-#define L_PTE_EXEC             (1 << 9)
-#define L_PTE_SHARED           (1 << 10)       /* shared(v6), coherent(xsc3) */
+#define L_PTE_PRESENT          (_AT(pteval_t, 1) << 0)
+#define L_PTE_YOUNG            (_AT(pteval_t, 1) << 1)
+#define L_PTE_FILE             (_AT(pteval_t, 1) << 2) /* only when !PRESENT */
+#define L_PTE_DIRTY            (_AT(pteval_t, 1) << 6)
+#define L_PTE_RDONLY           (_AT(pteval_t, 1) << 7)
+#define L_PTE_USER             (_AT(pteval_t, 1) << 8)
+#define L_PTE_XN               (_AT(pteval_t, 1) << 9)
+#define L_PTE_SHARED           (_AT(pteval_t, 1) << 10)        /* shared(v6), coherent(xsc3) */
 
 /*
  * These are the memory types, defined to be compatible with
  * pre-ARMv6 CPUs cacheable and bufferable bits:   XXCB
  */
-#define L_PTE_MT_UNCACHED      (0x00 << 2)     /* 0000 */
-#define L_PTE_MT_BUFFERABLE    (0x01 << 2)     /* 0001 */
-#define L_PTE_MT_WRITETHROUGH  (0x02 << 2)     /* 0010 */
-#define L_PTE_MT_WRITEBACK     (0x03 << 2)     /* 0011 */
-#define L_PTE_MT_MINICACHE     (0x06 << 2)     /* 0110 (sa1100, xscale) */
-#define L_PTE_MT_WRITEALLOC    (0x07 << 2)     /* 0111 */
-#define L_PTE_MT_DEV_SHARED    (0x04 << 2)     /* 0100 */
-#define L_PTE_MT_DEV_NONSHARED (0x0c << 2)     /* 1100 */
-#define L_PTE_MT_DEV_WC                (0x09 << 2)     /* 1001 */
-#define L_PTE_MT_DEV_CACHED    (0x0b << 2)     /* 1011 */
-#define L_PTE_MT_MASK          (0x0f << 2)
+#define L_PTE_MT_UNCACHED      (_AT(pteval_t, 0x00) << 2)      /* 0000 */
+#define L_PTE_MT_BUFFERABLE    (_AT(pteval_t, 0x01) << 2)      /* 0001 */
+#define L_PTE_MT_WRITETHROUGH  (_AT(pteval_t, 0x02) << 2)      /* 0010 */
+#define L_PTE_MT_WRITEBACK     (_AT(pteval_t, 0x03) << 2)      /* 0011 */
+#define L_PTE_MT_MINICACHE     (_AT(pteval_t, 0x06) << 2)      /* 0110 (sa1100, xscale) */
+#define L_PTE_MT_WRITEALLOC    (_AT(pteval_t, 0x07) << 2)      /* 0111 */
+#define L_PTE_MT_DEV_SHARED    (_AT(pteval_t, 0x04) << 2)      /* 0100 */
+#define L_PTE_MT_DEV_NONSHARED (_AT(pteval_t, 0x0c) << 2)      /* 1100 */
+#define L_PTE_MT_DEV_WC                (_AT(pteval_t, 0x09) << 2)      /* 1001 */
+#define L_PTE_MT_DEV_CACHED    (_AT(pteval_t, 0x0b) << 2)      /* 1011 */
+#define L_PTE_MT_MASK          (_AT(pteval_t, 0x0f) << 2)
 
 #ifndef __ASSEMBLY__
 
@@ -201,23 +205,44 @@ extern pgprot_t           pgprot_kernel;
 
 #define _MOD_PROT(p, b)        __pgprot(pgprot_val(p) | (b))
 
-#define PAGE_NONE              pgprot_user
-#define PAGE_SHARED            _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE)
-#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC)
-#define PAGE_COPY              _MOD_PROT(pgprot_user, L_PTE_USER)
-#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_EXEC)
-#define PAGE_READONLY          _MOD_PROT(pgprot_user, L_PTE_USER)
-#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_EXEC)
-#define PAGE_KERNEL            pgprot_kernel
-#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_kernel, L_PTE_EXEC)
-
-#define __PAGE_NONE            __pgprot(_L_PTE_DEFAULT)
-#define __PAGE_SHARED          __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE)
-#define __PAGE_SHARED_EXEC     __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_WRITE | L_PTE_EXEC)
-#define __PAGE_COPY            __pgprot(_L_PTE_DEFAULT | L_PTE_USER)
-#define __PAGE_COPY_EXEC       __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_EXEC)
-#define __PAGE_READONLY                __pgprot(_L_PTE_DEFAULT | L_PTE_USER)
-#define __PAGE_READONLY_EXEC   __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_EXEC)
+#define PAGE_NONE              _MOD_PROT(pgprot_user, L_PTE_XN | L_PTE_RDONLY)
+#define PAGE_SHARED            _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_XN)
+#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_user, L_PTE_USER)
+#define PAGE_COPY              _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
+#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY)
+#define PAGE_READONLY          _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
+#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_user, L_PTE_USER | L_PTE_RDONLY)
+#define PAGE_KERNEL            _MOD_PROT(pgprot_kernel, L_PTE_XN)
+#define PAGE_KERNEL_EXEC       pgprot_kernel
+
+#define __PAGE_NONE            __pgprot(_L_PTE_DEFAULT | L_PTE_RDONLY | L_PTE_XN)
+#define __PAGE_SHARED          __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_XN)
+#define __PAGE_SHARED_EXEC     __pgprot(_L_PTE_DEFAULT | L_PTE_USER)
+#define __PAGE_COPY            __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
+#define __PAGE_COPY_EXEC       __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY)
+#define __PAGE_READONLY                __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY | L_PTE_XN)
+#define __PAGE_READONLY_EXEC   __pgprot(_L_PTE_DEFAULT | L_PTE_USER | L_PTE_RDONLY)
+
+#define __pgprot_modify(prot,mask,bits)                \
+       __pgprot((pgprot_val(prot) & ~(mask)) | (bits))
+
+#define pgprot_noncached(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
+
+#define pgprot_writecombine(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
+
+#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
+#define pgprot_dmacoherent(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE | L_PTE_XN)
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                                    unsigned long size, pgprot_t vma_prot);
+#else
+#define pgprot_dmacoherent(prot) \
+       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN)
+#endif
 
 #endif /* __ASSEMBLY__ */
 
@@ -255,26 +280,84 @@ extern pgprot_t           pgprot_kernel;
 extern struct page *empty_zero_page;
 #define ZERO_PAGE(vaddr)       (empty_zero_page)
 
-#define pte_pfn(pte)           (pte_val(pte) >> PAGE_SHIFT)
-#define pfn_pte(pfn,prot)      (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 
-#define pte_none(pte)          (!pte_val(pte))
-#define pte_clear(mm,addr,ptep)        set_pte_ext(ptep, __pte(0), 0)
-#define pte_page(pte)          (pfn_to_page(pte_pfn(pte)))
-#define pte_offset_kernel(dir,addr)    (pmd_page_vaddr(*(dir)) + __pte_index(addr))
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(addr)                ((addr) >> PGDIR_SHIFT)
+
+#define pgd_offset(mm, addr)   ((mm)->pgd + pgd_index(addr))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)     pgd_offset(&init_mm, addr)
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+#define pgd_none(pgd)          (0)
+#define pgd_bad(pgd)           (0)
+#define pgd_present(pgd)       (1)
+#define pgd_clear(pgdp)                do { } while (0)
+#define set_pgd(pgd,pgdp)      do { } while (0)
+
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir, addr)  ((pmd_t *)(dir))
+
+#define pmd_none(pmd)          (!pmd_val(pmd))
+#define pmd_present(pmd)       (pmd_val(pmd))
+#define pmd_bad(pmd)           (pmd_val(pmd) & 2)
+
+#define copy_pmd(pmdpd,pmdps)          \
+       do {                            \
+               pmdpd[0] = pmdps[0];    \
+               pmdpd[1] = pmdps[1];    \
+               flush_pmd_entry(pmdpd); \
+       } while (0)
+
+#define pmd_clear(pmdp)                        \
+       do {                            \
+               pmdp[0] = __pmd(0);     \
+               pmdp[1] = __pmd(0);     \
+               clean_pmd_entry(pmdp);  \
+       } while (0)
+
+static inline pte_t *pmd_page_vaddr(pmd_t pmd)
+{
+       return __va(pmd_val(pmd) & PAGE_MASK);
+}
+
+#define pmd_page(pmd)          pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
+
+/* we don't need complex calculations here as the pmd is folded into the pgd */
+#define pmd_addr_end(addr,end) (end)
 
-#define pte_offset_map(dir,addr)       (__pte_map(dir) + __pte_index(addr))
-#define pte_unmap(pte)                 __pte_unmap(pte)
 
 #ifndef CONFIG_HIGHPTE
-#define __pte_map(dir)         pmd_page_vaddr(*(dir))
+#define __pte_map(pmd)         pmd_page_vaddr(*(pmd))
 #define __pte_unmap(pte)       do { } while (0)
 #else
-#define __pte_map(dir)         ((pte_t *)kmap_atomic(pmd_page(*(dir))) + PTRS_PER_PTE)
-#define __pte_unmap(pte)       kunmap_atomic((pte - PTRS_PER_PTE))
+#define __pte_map(pmd)         (pte_t *)kmap_atomic(pmd_page(*(pmd)))
+#define __pte_unmap(pte)       kunmap_atomic(pte)
 #endif
 
+#define pte_index(addr)                (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+#define pte_offset_kernel(pmd,addr)    (pmd_page_vaddr(*(pmd)) + pte_index(addr))
+
+#define pte_offset_map(pmd,addr)       (__pte_map(pmd) + pte_index(addr))
+#define pte_unmap(pte)                 __pte_unmap(pte)
+
+#define pte_pfn(pte)           (pte_val(pte) >> PAGE_SHIFT)
+#define pfn_pte(pfn,prot)      __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+
+#define pte_page(pte)          pfn_to_page(pte_pfn(pte))
+#define mk_pte(page,prot)      pfn_pte(page_to_pfn(page), prot)
+
 #define set_pte_ext(ptep,pte,ext) cpu_set_pte_ext(ptep,pte,ext)
+#define pte_clear(mm,addr,ptep)        set_pte_ext(ptep, __pte(0), 0)
 
 #if __LINUX_ARM_ARCH__ < 6
 static inline void __sync_icache_dcache(pte_t pteval)
@@ -295,15 +378,12 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
        }
 }
 
-/*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
- */
+#define pte_none(pte)          (!pte_val(pte))
 #define pte_present(pte)       (pte_val(pte) & L_PTE_PRESENT)
-#define pte_write(pte)         (pte_val(pte) & L_PTE_WRITE)
+#define pte_write(pte)         (!(pte_val(pte) & L_PTE_RDONLY))
 #define pte_dirty(pte)         (pte_val(pte) & L_PTE_DIRTY)
 #define pte_young(pte)         (pte_val(pte) & L_PTE_YOUNG)
-#define pte_exec(pte)          (pte_val(pte) & L_PTE_EXEC)
+#define pte_exec(pte)          (!(pte_val(pte) & L_PTE_XN))
 #define pte_special(pte)       (0)
 
 #define pte_present_user(pte) \
@@ -313,8 +393,8 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
-PTE_BIT_FUNC(wrprotect, &= ~L_PTE_WRITE);
-PTE_BIT_FUNC(mkwrite,   |= L_PTE_WRITE);
+PTE_BIT_FUNC(wrprotect, |= L_PTE_RDONLY);
+PTE_BIT_FUNC(mkwrite,   &= ~L_PTE_RDONLY);
 PTE_BIT_FUNC(mkclean,   &= ~L_PTE_DIRTY);
 PTE_BIT_FUNC(mkdirty,   |= L_PTE_DIRTY);
 PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
@@ -322,101 +402,13 @@ PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
 
 static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
 
-#define __pgprot_modify(prot,mask,bits)                \
-       __pgprot((pgprot_val(prot) & ~(mask)) | (bits))
-
-/*
- * Mark the prot value as uncacheable and unbufferable.
- */
-#define pgprot_noncached(prot) \
-       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED)
-#define pgprot_writecombine(prot) \
-       __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE)
-#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
-#define pgprot_dmacoherent(prot) \
-       __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_BUFFERABLE)
-#define __HAVE_PHYS_MEM_ACCESS_PROT
-struct file;
-extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
-                                    unsigned long size, pgprot_t vma_prot);
-#else
-#define pgprot_dmacoherent(prot) \
-       __pgprot_modify(prot, L_PTE_MT_MASK|L_PTE_EXEC, L_PTE_MT_UNCACHED)
-#endif
-
-#define pmd_none(pmd)          (!pmd_val(pmd))
-#define pmd_present(pmd)       (pmd_val(pmd))
-#define pmd_bad(pmd)           (pmd_val(pmd) & 2)
-
-#define copy_pmd(pmdpd,pmdps)          \
-       do {                            \
-               pmdpd[0] = pmdps[0];    \
-               pmdpd[1] = pmdps[1];    \
-               flush_pmd_entry(pmdpd); \
-       } while (0)
-
-#define pmd_clear(pmdp)                        \
-       do {                            \
-               pmdp[0] = __pmd(0);     \
-               pmdp[1] = __pmd(0);     \
-               clean_pmd_entry(pmdp);  \
-       } while (0)
-
-static inline pte_t *pmd_page_vaddr(pmd_t pmd)
-{
-       unsigned long ptr;
-
-       ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * sizeof(void *) - 1);
-       ptr += PTRS_PER_PTE * sizeof(void *);
-
-       return __va(ptr);
-}
-
-#define pmd_page(pmd)          pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
-
-/* we don't need complex calculations here as the pmd is folded into the pgd */
-#define pmd_addr_end(addr,end) (end)
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-#define mk_pte(page,prot)      pfn_pte(page_to_pfn(page),prot)
-
-/*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
- */
-#define pgd_none(pgd)          (0)
-#define pgd_bad(pgd)           (0)
-#define pgd_present(pgd)       (1)
-#define pgd_clear(pgdp)                do { } while (0)
-#define set_pgd(pgd,pgdp)      do { } while (0)
-
-/* to find an entry in a page-table-directory */
-#define pgd_index(addr)                ((addr) >> PGDIR_SHIFT)
-
-#define pgd_offset(mm, addr)   ((mm)->pgd+pgd_index(addr))
-
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(addr)     pgd_offset(&init_mm, addr)
-
-/* Find an entry in the second-level page table.. */
-#define pmd_offset(dir, addr)  ((pmd_t *)(dir))
-
-/* Find an entry in the third-level page table.. */
-#define __pte_index(addr)      (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
-
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       const unsigned long mask = L_PTE_EXEC | L_PTE_WRITE | L_PTE_USER;
+       const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER;
        pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
        return pte;
 }
 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
 /*
  * Encode and decode a swap entry.  Swap entries are stored in the Linux
  * page tables as follows:
@@ -481,6 +473,9 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 #define pgtable_cache_init() do { } while (0)
 
+void identity_mapping_add(pgd_t *, unsigned long, unsigned long);
+void identity_mapping_del(pgd_t *, unsigned long, unsigned long);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* CONFIG_MMU */
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h
new file mode 100644 (file)
index 0000000..a84628b
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * sched_clock.h: support for extending counters to full 64-bit ns counter
+ *
+ * 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_SCHED_CLOCK
+#define ASM_SCHED_CLOCK
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+struct clock_data {
+       u64 epoch_ns;
+       u32 epoch_cyc;
+       u32 epoch_cyc_copy;
+       u32 mult;
+       u32 shift;
+};
+
+#define DEFINE_CLOCK_DATA(name)        struct clock_data name
+
+static inline u64 cyc_to_ns(u64 cyc, u32 mult, u32 shift)
+{
+       return (cyc * mult) >> shift;
+}
+
+/*
+ * Atomically update the sched_clock epoch.  Your update callback will
+ * be called from a timer before the counter wraps - read the current
+ * counter value, and call this function to safely move the epochs
+ * forward.  Only use this from the update callback.
+ */
+static inline void update_sched_clock(struct clock_data *cd, u32 cyc, u32 mask)
+{
+       unsigned long flags;
+       u64 ns = cd->epoch_ns +
+               cyc_to_ns((cyc - cd->epoch_cyc) & mask, cd->mult, cd->shift);
+
+       /*
+        * Write epoch_cyc and epoch_ns in a way that the update is
+        * detectable in cyc_to_fixed_sched_clock().
+        */
+       raw_local_irq_save(flags);
+       cd->epoch_cyc = cyc;
+       smp_wmb();
+       cd->epoch_ns = ns;
+       smp_wmb();
+       cd->epoch_cyc_copy = cyc;
+       raw_local_irq_restore(flags);
+}
+
+/*
+ * If your clock rate is known at compile time, using this will allow
+ * you to optimize the mult/shift loads away.  This is paired with
+ * init_fixed_sched_clock() to ensure that your mult/shift are correct.
+ */
+static inline unsigned long long cyc_to_fixed_sched_clock(struct clock_data *cd,
+       u32 cyc, u32 mask, u32 mult, u32 shift)
+{
+       u64 epoch_ns;
+       u32 epoch_cyc;
+
+       /*
+        * Load the epoch_cyc and epoch_ns atomically.  We do this by
+        * ensuring that we always write epoch_cyc, epoch_ns and
+        * epoch_cyc_copy in strict order, and read them in strict order.
+        * If epoch_cyc and epoch_cyc_copy are not equal, then we're in
+        * the middle of an update, and we should repeat the load.
+        */
+       do {
+               epoch_cyc = cd->epoch_cyc;
+               smp_rmb();
+               epoch_ns = cd->epoch_ns;
+               smp_rmb();
+       } while (epoch_cyc != cd->epoch_cyc_copy);
+
+       return epoch_ns + cyc_to_ns((cyc - epoch_cyc) & mask, mult, shift);
+}
+
+/*
+ * Otherwise, you need to use this, which will obtain the mult/shift
+ * from the clock_data structure.  Use init_sched_clock() with this.
+ */
+static inline unsigned long long cyc_to_sched_clock(struct clock_data *cd,
+       u32 cyc, u32 mask)
+{
+       return cyc_to_fixed_sched_clock(cd, cyc, mask, cd->mult, cd->shift);
+}
+
+/*
+ * Initialize the clock data - calculate the appropriate multiplier
+ * and shift.  Also setup a timer to ensure that the epoch is refreshed
+ * at the appropriate time interval, which will call your update
+ * handler.
+ */
+void init_sched_clock(struct clock_data *, void (*)(void),
+       unsigned int, unsigned long);
+
+/*
+ * Use this initialization function rather than init_sched_clock() if
+ * you're using cyc_to_fixed_sched_clock, which will warn if your
+ * constants are incorrect.
+ */
+static inline void init_fixed_sched_clock(struct clock_data *cd,
+       void (*update)(void), unsigned int bits, unsigned long rate,
+       u32 mult, u32 shift)
+{
+       init_sched_clock(cd, update, bits, rate);
+       if (cd->mult != mult || cd->shift != shift) {
+               pr_crit("sched_clock: wrong multiply/shift: %u>>%u vs calculated %u>>%u\n"
+                       "sched_clock: fix multiply/shift to avoid scheduler hiccups\n",
+                       mult, shift, cd->mult, cd->shift);
+       }
+}
+
+#endif
index 4fc1565e4f930860722bca331330d0606e494d1c..316bb2b2be3dd7ca64638ea2d13d502e66ee5fde 100644 (file)
@@ -13,9 +13,6 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-/* DO NOT EDIT!! - this file automatically generated
- *                 from .s file by awk -f s2h.awk
- */
 /*  Size definitions
  *  Copyright (C) ARM Limited 1998. All rights reserved.
  */
@@ -25,6 +22,9 @@
 
 /* handy sizes */
 #define SZ_16                          0x00000010
+#define SZ_32                          0x00000020
+#define SZ_64                          0x00000040
+#define SZ_128                         0x00000080
 #define SZ_256                         0x00000100
 #define SZ_512                         0x00000200
 
index 3d05190797cbf515a9c85f33ac49f98818b76cb6..96ed521f240877cd20a7d44df4c24b1481aae4f6 100644 (file)
@@ -33,27 +33,23 @@ struct seq_file;
 /*
  * generate IPI list text
  */
-extern void show_ipi_list(struct seq_file *p);
+extern void show_ipi_list(struct seq_file *, int);
 
 /*
  * Called from assembly code, this handles an IPI.
  */
-asmlinkage void do_IPI(struct pt_regs *regs);
+asmlinkage void do_IPI(int ipinr, struct pt_regs *regs);
 
 /*
  * Setup the set of possible CPUs (via set_cpu_possible)
  */
 extern void smp_init_cpus(void);
 
-/*
- * Move global data into per-processor storage.
- */
-extern void smp_store_cpu_info(unsigned int cpuid);
 
 /*
  * Raise an IPI cross call on CPUs in callmap.
  */
-extern void smp_cross_call(const struct cpumask *mask);
+extern void smp_cross_call(const struct cpumask *mask, int ipi);
 
 /*
  * Boot a secondary CPU, and assign it the specified idle task.
@@ -72,6 +68,11 @@ asmlinkage void secondary_start_kernel(void);
  */
 extern void platform_secondary_init(unsigned int cpu);
 
+/*
+ * Initialize cpu_possible map, and enable coherency
+ */
+extern void platform_smp_prepare_cpus(unsigned int);
+
 /*
  * Initial data for bringing up a secondary CPU.
  */
@@ -97,6 +98,6 @@ extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 /*
  * show local interrupt info
  */
-extern void show_local_irqs(struct seq_file *);
+extern void show_local_irqs(struct seq_file *, int);
 
 #endif /* ifndef __ASM_ARM_SMP_H */
diff --git a/arch/arm/include/asm/smp_mpidr.h b/arch/arm/include/asm/smp_mpidr.h
deleted file mode 100644 (file)
index 6a9307d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef ASMARM_SMP_MIDR_H
-#define ASMARM_SMP_MIDR_H
-
-#define hard_smp_processor_id()                                                \
-       ({                                                              \
-               unsigned int cpunum;                                    \
-               __asm__("\n"                                            \
-                       "1:     mrc p15, 0, %0, c0, c0, 5\n"            \
-                       "       .pushsection \".alt.smp.init\", \"a\"\n"\
-                       "       .long   1b\n"                           \
-                       "       mov     %0, #0\n"                       \
-                       "       .popsection"                            \
-                       : "=r" (cpunum));                               \
-               cpunum &= 0x0F;                                         \
-       })
-
-#endif
index 634f357be6bb787d8a578cfa90a99b7742529b19..fed9981fba08feec85a09b094215036a7e8839b1 100644 (file)
@@ -22,7 +22,6 @@ struct clock_event_device;
 
 extern void __iomem *twd_base;
 
-void twd_timer_stop(void);
 int twd_timer_ack(void);
 void twd_timer_setup(struct clock_event_device *);
 
index ec4327a4653d45c7e1e3fe6bb1e142d8fadce2e8..97f6d60297d576c861a32590568e95a15ff78211 100644 (file)
@@ -124,6 +124,13 @@ extern unsigned int user_debug;
 #define vectors_high() (0)
 #endif
 
+#if __LINUX_ARM_ARCH__ >= 7 ||         \
+       (__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
+#define sev()  __asm__ __volatile__ ("sev" : : : "memory")
+#define wfe()  __asm__ __volatile__ ("wfe" : : : "memory")
+#define wfi()  __asm__ __volatile__ ("wfi" : : : "memory")
+#endif
+
 #if __LINUX_ARM_ARCH__ >= 7
 #define isb() __asm__ __volatile__ ("isb" : : : "memory")
 #define dsb() __asm__ __volatile__ ("dsb" : : : "memory")
@@ -155,6 +162,7 @@ extern unsigned int user_debug;
 #define rmb()          dmb()
 #define wmb()          mb()
 #else
+#include <asm/memory.h>
 #define mb()   do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
 #define rmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
 #define wmb()  do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
index 124475afb00719a5da9ceda00c4883358dc8052a..1b960d5ef6a5d1bdb1afd5bc804136aa61f1e19a 100644 (file)
@@ -46,4 +46,6 @@ static inline int in_exception_text(unsigned long ptr)
 extern void __init early_trap_init(void);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
 
+extern void *vectors_page;
+
 #endif
index 33e4a48fe1037575d4d6e212000a8aa01303f7fc..b293616a1a1a8d6cf92a5ae1560994c7e3d66e46 100644 (file)
@@ -227,7 +227,7 @@ do {                                                                        \
 
 #define __get_user_asm_byte(x,addr,err)                                \
        __asm__ __volatile__(                                   \
-       "1:     ldrbt   %1,[%2]\n"                              \
+       "1:     " T(ldrb) "     %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -263,7 +263,7 @@ do {                                                                        \
 
 #define __get_user_asm_word(x,addr,err)                                \
        __asm__ __volatile__(                                   \
-       "1:     ldrt    %1,[%2]\n"                              \
+       "1:     " T(ldr) "      %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -308,7 +308,7 @@ do {                                                                        \
 
 #define __put_user_asm_byte(x,__pu_addr,err)                   \
        __asm__ __volatile__(                                   \
-       "1:     strbt   %1,[%2]\n"                              \
+       "1:     " T(strb) "     %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -341,7 +341,7 @@ do {                                                                        \
 
 #define __put_user_asm_word(x,__pu_addr,err)                   \
        __asm__ __volatile__(                                   \
-       "1:     strt    %1,[%2]\n"                              \
+       "1:     " T(str) "      %1,[%2],#0\n"                   \
        "2:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
@@ -366,10 +366,10 @@ do {                                                                      \
 
 #define __put_user_asm_dword(x,__pu_addr,err)                  \
        __asm__ __volatile__(                                   \
- ARM(  "1:     strt    " __reg_oper1 ", [%1], #4\n"    )       \
- ARM(  "2:     strt    " __reg_oper0 ", [%1]\n"        )       \
- THUMB(        "1:     strt    " __reg_oper1 ", [%1]\n"        )       \
- THUMB(        "2:     strt    " __reg_oper0 ", [%1, #4]\n"    )       \
+ ARM(  "1:     " T(str) "      " __reg_oper1 ", [%1], #4\n"    )       \
+ ARM(  "2:     " T(str) "      " __reg_oper0 ", [%1]\n"        )       \
+ THUMB(        "1:     " T(str) "      " __reg_oper1 ", [%1]\n"        )       \
+ THUMB(        "2:     " T(str) "      " __reg_oper0 ", [%1, #4]\n"    )       \
        "3:\n"                                                  \
        "       .pushsection .fixup,\"ax\"\n"                   \
        "       .align  2\n"                                    \
index c73abe4b7e7274e030928f1e702c98b7ddb07e0f..185ee822c9353ee203d1a8adf6d6aefce26762fa 100644 (file)
@@ -29,7 +29,8 @@ obj-$(CONFIG_MODULES)         += armksyms.o module.o
 obj-$(CONFIG_ARTHUR)           += arthur.o
 obj-$(CONFIG_ISA_DMA)          += dma-isa.o
 obj-$(CONFIG_PCI)              += bios32.o isa.o
-obj-$(CONFIG_SMP)              += smp.o
+obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
+obj-$(CONFIG_SMP)              += smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)     += smp_scu.o
 obj-$(CONFIG_HAVE_ARM_TWD)     += smp_twd.o
 obj-$(CONFIG_DYNAMIC_FTRACE)   += ftrace.o
@@ -43,6 +44,8 @@ obj-$(CONFIG_KGDB)            += kgdb.o
 obj-$(CONFIG_ARM_UNWIND)       += unwind.o
 obj-$(CONFIG_HAVE_TCM)         += tcm.o
 obj-$(CONFIG_CRASH_DUMP)       += crash_dump.o
+obj-$(CONFIG_SWP_EMULATE)      += swp_emulate.o
+CFLAGS_swp_emulate.o           := -Wa,-march=armv7-a
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += hw_breakpoint.o
 
 obj-$(CONFIG_CRUNCH)           += crunch.o crunch-bits.o
index 36199ffc4cc21a3d7c83282340f8829fd1775050..2b46fea36c9fa30ab41c3747686d40eb2f64e67f 100644 (file)
 #include <asm/tls.h>
 
 #include "entry-header.S"
+#include <asm/entry-macro-multi.S>
 
 /*
  * Interrupt handling.  Preserves r7, r8, r9
  */
        .macro  irq_handler
-       get_irqnr_preamble r5, lr
-1:     get_irqnr_and_base r0, r6, r5, lr
-       movne   r1, sp
-       @
-       @ routine called with r0 = irq number, r1 = struct pt_regs *
-       @
-       adrne   lr, BSYM(1b)
-       bne     asm_do_IRQ
-
-#ifdef CONFIG_SMP
-       /*
-        * XXX
-        *
-        * this macro assumes that irqstat (r6) and base (r5) are
-        * preserved from get_irqnr_and_base above
-        */
-       ALT_SMP(test_for_ipi r0, r6, r5, lr)
-       ALT_UP_B(9997f)
-       movne   r0, sp
-       adrne   lr, BSYM(1b)
-       bne     do_IPI
-
-#ifdef CONFIG_LOCAL_TIMERS
-       test_for_ltirq r0, r6, r5, lr
-       movne   r0, sp
-       adrne   lr, BSYM(1b)
-       bne     do_local_timer
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+       ldr     r5, =handle_arch_irq
+       mov     r0, sp
+       ldr     r5, [r5]
+       adr     lr, BSYM(9997f)
+       teq     r5, #0
+       movne   pc, r5
 #endif
+       arch_irq_handler_default
 9997:
-#endif
-
        .endm
 
 #ifdef CONFIG_KPROBES
@@ -739,7 +719,7 @@ ENTRY(__switch_to)
  THUMB(        stmia   ip!, {r4 - sl, fp}         )    @ Store most regs on stack
  THUMB(        str     sp, [ip], #4               )
  THUMB(        str     lr, [ip], #4               )
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
        ldr     r6, [r2, #TI_CPU_DOMAIN]
 #endif
        set_tls r3, r4, r5
@@ -748,7 +728,7 @@ ENTRY(__switch_to)
        ldr     r8, =__stack_chk_guard
        ldr     r7, [r7, #TSK_STACK_CANARY]
 #endif
-#ifdef CONFIG_MMU
+#ifdef CONFIG_CPU_USE_DOMAINS
        mcr     p15, 0, r6, c3, c0, 0           @ Set domain register
 #endif
        mov     r5, r0
@@ -846,7 +826,7 @@ __kuser_helper_start:
  */
 
 __kuser_memory_barrier:                                @ 0xffff0fa0
-       smp_dmb
+       smp_dmb arm
        usr_ret lr
 
        .align  5
@@ -963,7 +943,7 @@ kuser_cmpxchg_fixup:
 
 #else
 
-       smp_dmb
+       smp_dmb arm
 1:     ldrex   r3, [r2]
        subs    r3, r3, r0
        strexeq r3, r1, [r2]
@@ -1249,3 +1229,9 @@ cr_alignment:
        .space  4
 cr_no_alignment:
        .space  4
+
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+       .globl  handle_arch_irq
+handle_arch_irq:
+       .space  4
+#endif
index aae802ee12f86bad23e8fd2430ce5d206da28036..1e7b04a40a3164f7226ce82907012acb231fec45 100644 (file)
@@ -29,6 +29,9 @@ ret_fast_syscall:
        ldr     r1, [tsk, #TI_FLAGS]
        tst     r1, #_TIF_WORK_MASK
        bne     fast_work_pending
+#if defined(CONFIG_IRQSOFF_TRACER)
+       asm_trace_hardirqs_on
+#endif
 
        /* perform architecture specific actions before user return */
        arch_ret_to_user r1, lr
@@ -65,6 +68,9 @@ ret_slow_syscall:
        tst     r1, #_TIF_WORK_MASK
        bne     work_pending
 no_work_pending:
+#if defined(CONFIG_IRQSOFF_TRACER)
+       asm_trace_hardirqs_on
+#endif
        /* perform architecture specific actions before user return */
        arch_ret_to_user r1, lr
 
index 6ff7919613d7de1225ec1ca23c1003511194e048..e72dc34eea1cfbd0f3202067c1a937c4a20821d2 100644 (file)
@@ -45,6 +45,7 @@
 #include <asm/fiq.h>
 #include <asm/irq.h>
 #include <asm/system.h>
+#include <asm/traps.h>
 
 static unsigned long no_fiq_insn;
 
@@ -67,17 +68,22 @@ static struct fiq_handler default_owner = {
 
 static struct fiq_handler *current_fiq = &default_owner;
 
-int show_fiq_list(struct seq_file *p, void *v)
+int show_fiq_list(struct seq_file *p, int prec)
 {
        if (current_fiq != &default_owner)
-               seq_printf(p, "FIQ:              %s\n", current_fiq->name);
+               seq_printf(p, "%*s:              %s\n", prec, "FIQ",
+                       current_fiq->name);
 
        return 0;
 }
 
 void set_fiq_handler(void *start, unsigned int length)
 {
+#if defined(CONFIG_CPU_USE_DOMAINS)
        memcpy((void *)0xffff001c, start, length);
+#else
+       memcpy(vectors_page + 0x1c, start, length);
+#endif
        flush_icache_range(0xffff001c, 0xffff001c + length);
        if (!vectors_high())
                flush_icache_range(0x1c, 0x1c + length);
index 6bd82d25683c3a81946d072825cef42f25628643..f17d9a09e8fbf115c26a1f169553d2f6034c4d45 100644 (file)
@@ -91,6 +91,11 @@ ENTRY(stext)
        movs    r8, r5                          @ invalid machine (r5=0)?
  THUMB( it     eq )            @ force fixup-able long branch encoding
        beq     __error_a                       @ yes, error 'a'
+
+       /*
+        * r1 = machine no, r2 = atags,
+        * r8 = machinfo, r9 = cpuid, r10 = procinfo
+        */
        bl      __vet_atags
 #ifdef CONFIG_SMP_ON_UP
        bl      __fixup_smp
@@ -387,19 +392,19 @@ ENDPROC(__turn_mmu_on)
 
 #ifdef CONFIG_SMP_ON_UP
 __fixup_smp:
-       mov     r7, #0x00070000
-       orr     r6, r7, #0xff000000     @ mask 0xff070000
-       orr     r7, r7, #0x41000000     @ val 0x41070000
-       and     r0, r9, r6
-       teq     r0, r7                  @ ARM CPU and ARMv6/v7?
+       mov     r4, #0x00070000
+       orr     r3, r4, #0xff000000     @ mask 0xff070000
+       orr     r4, r4, #0x41000000     @ val 0x41070000
+       and     r0, r9, r3
+       teq     r0, r4                  @ ARM CPU and ARMv6/v7?
        bne     __fixup_smp_on_up       @ no, assume UP
 
-       orr     r6, r6, #0x0000ff00
-       orr     r6, r6, #0x000000f0     @ mask 0xff07fff0
-       orr     r7, r7, #0x0000b000
-       orr     r7, r7, #0x00000020     @ val 0x4107b020
-       and     r0, r9, r6
-       teq     r0, r7                  @ ARM 11MPCore?
+       orr     r3, r3, #0x0000ff00
+       orr     r3, r3, #0x000000f0     @ mask 0xff07fff0
+       orr     r4, r4, #0x0000b000
+       orr     r4, r4, #0x00000020     @ val 0x4107b020
+       and     r0, r9, r3
+       teq     r0, r4                  @ ARM 11MPCore?
        moveq   pc, lr                  @ yes, assume SMP
 
        mrc     p15, 0, r0, c0, c0, 5   @ read MPIDR
@@ -408,15 +413,22 @@ __fixup_smp:
 
 __fixup_smp_on_up:
        adr     r0, 1f
-       ldmia   r0, {r3, r6, r7}
+       ldmia   r0, {r3 - r5}
        sub     r3, r0, r3
-       add     r6, r6, r3
-       add     r7, r7, r3
-2:     cmp     r6, r7
-       ldmia   r6!, {r0, r4}
-       strlo   r4, [r0, r3]
-       blo     2b
-       mov     pc, lr
+       add     r4, r4, r3
+       add     r5, r5, r3
+2:     cmp     r4, r5
+       movhs   pc, lr
+       ldmia   r4!, {r0, r6}
+ ARM(  str     r6, [r0, r3]    )
+ THUMB(        add     r0, r0, r3      )
+#ifdef __ARMEB__
+ THUMB(        mov     r6, r6, ror #16 )       @ Convert word order for big-endian.
+#endif
+ THUMB(        strh    r6, [r0], #2    )       @ For Thumb-2, store as two halfwords
+ THUMB(        mov     r6, r6, lsr #16 )       @ to be robust against misaligned r3.
+ THUMB(        strh    r6, [r0]        )
+       b       2b
 ENDPROC(__fixup_smp)
 
        .align
index 6d616333340f1a97fdcaf1f8d591ac58c39da3bb..8135438b8818a37533e4772bd8cf4adb3cb8b172 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/ftrace.h>
 
 #include <asm/system.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
@@ -48,8 +49,6 @@
 #define irq_finish(irq) do { } while (0)
 #endif
 
-unsigned int arch_nr_irqs;
-void (*init_arch_irq)(void) __initdata = NULL;
 unsigned long irq_err_count;
 
 int show_interrupts(struct seq_file *p, void *v)
@@ -58,11 +57,20 @@ int show_interrupts(struct seq_file *p, void *v)
        struct irq_desc *desc;
        struct irqaction * action;
        unsigned long flags;
+       int prec, n;
+
+       for (prec = 3, n = 1000; prec < 10 && n <= nr_irqs; prec++)
+               n *= 10;
+
+#ifdef CONFIG_SMP
+       if (prec < 4)
+               prec = 4;
+#endif
 
        if (i == 0) {
                char cpuname[12];
 
-               seq_printf(p, "    ");
+               seq_printf(p, "%*s ", prec, "");
                for_each_present_cpu(cpu) {
                        sprintf(cpuname, "CPU%d", cpu);
                        seq_printf(p, " %10s", cpuname);
@@ -77,7 +85,7 @@ int show_interrupts(struct seq_file *p, void *v)
                if (!action)
                        goto unlock;
 
-               seq_printf(p, "%3d: ", i);
+               seq_printf(p, "%*d: ", prec, i);
                for_each_present_cpu(cpu)
                        seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
                seq_printf(p, " %10s", desc->chip->name ? : "-");
@@ -90,13 +98,15 @@ unlock:
                raw_spin_unlock_irqrestore(&desc->lock, flags);
        } else if (i == nr_irqs) {
 #ifdef CONFIG_FIQ
-               show_fiq_list(p, v);
+               show_fiq_list(p, prec);
 #endif
 #ifdef CONFIG_SMP
-               show_ipi_list(p);
-               show_local_irqs(p);
+               show_ipi_list(p, prec);
+#endif
+#ifdef CONFIG_LOCAL_TIMERS
+               show_local_irqs(p, prec);
 #endif
-               seq_printf(p, "Err: %10lu\n", irq_err_count);
+               seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
        }
        return 0;
 }
@@ -156,13 +166,13 @@ void set_irq_flags(unsigned int irq, unsigned int iflags)
 
 void __init init_IRQ(void)
 {
-       init_arch_irq();
+       machine_desc->init_irq();
 }
 
 #ifdef CONFIG_SPARSE_IRQ
 int __init arch_probe_nr_irqs(void)
 {
-       nr_irqs = arch_nr_irqs ? arch_nr_irqs : NR_IRQS;
+       nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS;
        return nr_irqs;
 }
 #endif
index 3a8fd5140d7a52ef33c8bfc444384ab8bc25c84a..30ead135ff5f48350192291a32662b0d3d0429d5 100644 (file)
@@ -23,6 +23,8 @@ extern unsigned long kexec_indirection_page;
 extern unsigned long kexec_mach_type;
 extern unsigned long kexec_boot_atags;
 
+static atomic_t waiting_for_crash_ipi;
+
 /*
  * Provide a dummy crash_notes definition while crash dump arrives to arm.
  * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
@@ -37,9 +39,37 @@ void machine_kexec_cleanup(struct kimage *image)
 {
 }
 
+void machine_crash_nonpanic_core(void *unused)
+{
+       struct pt_regs regs;
+
+       crash_setup_regs(&regs, NULL);
+       printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
+              smp_processor_id());
+       crash_save_cpu(&regs, smp_processor_id());
+       flush_cache_all();
+
+       atomic_dec(&waiting_for_crash_ipi);
+       while (1)
+               cpu_relax();
+}
+
 void machine_crash_shutdown(struct pt_regs *regs)
 {
+       unsigned long msecs;
+
        local_irq_disable();
+
+       atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+       smp_call_function(machine_crash_nonpanic_core, NULL, false);
+       msecs = 1000; /* Wait at most a second for the other cpus to stop */
+       while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+               mdelay(1);
+               msecs--;
+       }
+       if (atomic_read(&waiting_for_crash_ipi) > 0)
+               printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
+
        crash_save_cpu(regs, smp_processor_id());
 
        printk(KERN_INFO "Loading crashdump kernel...\n");
index d9bd786ce23dc1228ac7937ad442292f08c74cca..0c1bb68ff4a8449b5884949dc3498404532bb293 100644 (file)
@@ -67,35 +67,6 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
                              char *secstrings,
                              struct module *mod)
 {
-#ifdef CONFIG_ARM_UNWIND
-       Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
-       struct arm_unwind_mapping *maps = mod->arch.map;
-
-       for (s = sechdrs; s < sechdrs_end; s++) {
-               char const *secname = secstrings + s->sh_name;
-
-               if (strcmp(".ARM.exidx.init.text", secname) == 0)
-                       maps[ARM_SEC_INIT].unw_sec = s;
-               else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
-                       maps[ARM_SEC_DEVINIT].unw_sec = s;
-               else if (strcmp(".ARM.exidx", secname) == 0)
-                       maps[ARM_SEC_CORE].unw_sec = s;
-               else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
-                       maps[ARM_SEC_EXIT].unw_sec = s;
-               else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
-                       maps[ARM_SEC_DEVEXIT].unw_sec = s;
-               else if (strcmp(".init.text", secname) == 0)
-                       maps[ARM_SEC_INIT].sec_text = s;
-               else if (strcmp(".devinit.text", secname) == 0)
-                       maps[ARM_SEC_DEVINIT].sec_text = s;
-               else if (strcmp(".text", secname) == 0)
-                       maps[ARM_SEC_CORE].sec_text = s;
-               else if (strcmp(".exit.text", secname) == 0)
-                       maps[ARM_SEC_EXIT].sec_text = s;
-               else if (strcmp(".devexit.text", secname) == 0)
-                       maps[ARM_SEC_DEVEXIT].sec_text = s;
-       }
-#endif
        return 0;
 }
 
@@ -300,41 +271,69 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
        return -ENOEXEC;
 }
 
-#ifdef CONFIG_ARM_UNWIND
-static void register_unwind_tables(struct module *mod)
+struct mod_unwind_map {
+       const Elf_Shdr *unw_sec;
+       const Elf_Shdr *txt_sec;
+};
+
+int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
+                   struct module *mod)
 {
+#ifdef CONFIG_ARM_UNWIND
+       const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+       const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+       struct mod_unwind_map maps[ARM_SEC_MAX];
        int i;
-       for (i = 0; i < ARM_SEC_MAX; ++i) {
-               struct arm_unwind_mapping *map = &mod->arch.map[i];
-               if (map->unw_sec && map->sec_text)
-                       map->unwind = unwind_table_add(map->unw_sec->sh_addr,
-                                                      map->unw_sec->sh_size,
-                                                      map->sec_text->sh_addr,
-                                                      map->sec_text->sh_size);
+
+       memset(maps, 0, sizeof(maps));
+
+       for (s = sechdrs; s < sechdrs_end; s++) {
+               const char *secname = secstrs + s->sh_name;
+
+               if (!(s->sh_flags & SHF_ALLOC))
+                       continue;
+
+               if (strcmp(".ARM.exidx.init.text", secname) == 0)
+                       maps[ARM_SEC_INIT].unw_sec = s;
+               else if (strcmp(".ARM.exidx.devinit.text", secname) == 0)
+                       maps[ARM_SEC_DEVINIT].unw_sec = s;
+               else if (strcmp(".ARM.exidx", secname) == 0)
+                       maps[ARM_SEC_CORE].unw_sec = s;
+               else if (strcmp(".ARM.exidx.exit.text", secname) == 0)
+                       maps[ARM_SEC_EXIT].unw_sec = s;
+               else if (strcmp(".ARM.exidx.devexit.text", secname) == 0)
+                       maps[ARM_SEC_DEVEXIT].unw_sec = s;
+               else if (strcmp(".init.text", secname) == 0)
+                       maps[ARM_SEC_INIT].txt_sec = s;
+               else if (strcmp(".devinit.text", secname) == 0)
+                       maps[ARM_SEC_DEVINIT].txt_sec = s;
+               else if (strcmp(".text", secname) == 0)
+                       maps[ARM_SEC_CORE].txt_sec = s;
+               else if (strcmp(".exit.text", secname) == 0)
+                       maps[ARM_SEC_EXIT].txt_sec = s;
+               else if (strcmp(".devexit.text", secname) == 0)
+                       maps[ARM_SEC_DEVEXIT].txt_sec = s;
        }
-}
 
-static void unregister_unwind_tables(struct module *mod)
-{
-       int i = ARM_SEC_MAX;
-       while (--i >= 0)
-               unwind_table_del(mod->arch.map[i].unwind);
-}
-#else
-static inline void register_unwind_tables(struct module *mod) { }
-static inline void unregister_unwind_tables(struct module *mod) { }
+       for (i = 0; i < ARM_SEC_MAX; i++)
+               if (maps[i].unw_sec && maps[i].txt_sec)
+                       mod->arch.unwind[i] =
+                               unwind_table_add(maps[i].unw_sec->sh_addr,
+                                                maps[i].unw_sec->sh_size,
+                                                maps[i].txt_sec->sh_addr,
+                                                maps[i].txt_sec->sh_size);
 #endif
-
-int
-module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
-               struct module *module)
-{
-       register_unwind_tables(module);
        return 0;
 }
 
 void
 module_arch_cleanup(struct module *mod)
 {
-       unregister_unwind_tables(mod);
+#ifdef CONFIG_ARM_UNWIND
+       int i;
+
+       for (i = 0; i < ARM_SEC_MAX; i++)
+               if (mod->arch.unwind[i])
+                       unwind_table_del(mod->arch.unwind[i]);
+#endif
 }
diff --git a/arch/arm/kernel/sched_clock.c b/arch/arm/kernel/sched_clock.c
new file mode 100644 (file)
index 0000000..2cdcc92
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * sched_clock.c: support for extending counters to full 64-bit ns counter
+ *
+ * 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/clocksource.h>
+#include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+
+#include <asm/sched_clock.h>
+
+static void sched_clock_poll(unsigned long wrap_ticks);
+static DEFINE_TIMER(sched_clock_timer, sched_clock_poll, 0, 0);
+static void (*sched_clock_update_fn)(void);
+
+static void sched_clock_poll(unsigned long wrap_ticks)
+{
+       mod_timer(&sched_clock_timer, round_jiffies(jiffies + wrap_ticks));
+       sched_clock_update_fn();
+}
+
+void __init init_sched_clock(struct clock_data *cd, void (*update)(void),
+       unsigned int clock_bits, unsigned long rate)
+{
+       unsigned long r, w;
+       u64 res, wrap;
+       char r_unit;
+
+       sched_clock_update_fn = update;
+
+       /* calculate the mult/shift to convert counter ticks to ns. */
+       clocks_calc_mult_shift(&cd->mult, &cd->shift, rate, NSEC_PER_SEC, 60);
+
+       r = rate;
+       if (r >= 4000000) {
+               r /= 1000000;
+               r_unit = 'M';
+       } else {
+               r /= 1000;
+               r_unit = 'k';
+       }
+
+       /* calculate how many ns until we wrap */
+       wrap = cyc_to_ns((1ULL << clock_bits) - 1, cd->mult, cd->shift);
+       do_div(wrap, NSEC_PER_MSEC);
+       w = wrap;
+
+       /* calculate the ns resolution of this counter */
+       res = cyc_to_ns(1ULL, cd->mult, cd->shift);
+       pr_info("sched_clock: %u bits at %lu%cHz, resolution %lluns, wraps every %lums\n",
+               clock_bits, r, r_unit, res, w);
+
+       /*
+        * Start the timer to keep sched_clock() properly updated and
+        * sets the initial epoch.
+        */
+       sched_clock_timer.data = msecs_to_jiffies(w - (w / 10));
+       sched_clock_poll(sched_clock_timer.data);
+
+       /*
+        * Ensure that sched_clock() starts off at 0ns
+        */
+       cd->epoch_ns = 0;
+}
index 336f14e0e5c212685c09f13f8ecbb30662873354..3455ad33de4c425bfdba98b7bef29999792f54e3 100644 (file)
@@ -75,9 +75,9 @@ extern void reboot_setup(char *str);
 
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
-unsigned int __machine_arch_type;
+unsigned int __machine_arch_type __read_mostly;
 EXPORT_SYMBOL(__machine_arch_type);
-unsigned int cacheid;
+unsigned int cacheid __read_mostly;
 EXPORT_SYMBOL(cacheid);
 
 unsigned int __atags_pointer __initdata;
@@ -91,24 +91,24 @@ EXPORT_SYMBOL(system_serial_low);
 unsigned int system_serial_high;
 EXPORT_SYMBOL(system_serial_high);
 
-unsigned int elf_hwcap;
+unsigned int elf_hwcap __read_mostly;
 EXPORT_SYMBOL(elf_hwcap);
 
 
 #ifdef MULTI_CPU
-struct processor processor;
+struct processor processor __read_mostly;
 #endif
 #ifdef MULTI_TLB
-struct cpu_tlb_fns cpu_tlb;
+struct cpu_tlb_fns cpu_tlb __read_mostly;
 #endif
 #ifdef MULTI_USER
-struct cpu_user_fns cpu_user;
+struct cpu_user_fns cpu_user __read_mostly;
 #endif
 #ifdef MULTI_CACHE
-struct cpu_cache_fns cpu_cache;
+struct cpu_cache_fns cpu_cache __read_mostly;
 #endif
 #ifdef CONFIG_OUTER_CACHE
-struct outer_cache_fns outer_cache;
+struct outer_cache_fns outer_cache __read_mostly;
 EXPORT_SYMBOL(outer_cache);
 #endif
 
@@ -126,6 +126,7 @@ EXPORT_SYMBOL(elf_platform);
 static const char *cpu_name;
 static const char *machine_name;
 static char __initdata cmd_line[COMMAND_LINE_SIZE];
+struct machine_desc *machine_desc __initdata;
 
 static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
 static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
@@ -708,13 +709,11 @@ static struct init_tags {
        { 0, ATAG_NONE }
 };
 
-static void (*init_machine)(void) __initdata;
-
 static int __init customize_machine(void)
 {
        /* customizes platform devices, or adds new ones */
-       if (init_machine)
-               init_machine();
+       if (machine_desc->init_machine)
+               machine_desc->init_machine();
        return 0;
 }
 arch_initcall(customize_machine);
@@ -809,6 +808,7 @@ void __init setup_arch(char **cmdline_p)
 
        setup_processor();
        mdesc = setup_machine(machine_arch_type);
+       machine_desc = mdesc;
        machine_name = mdesc->name;
 
        if (mdesc->soft_reboot)
@@ -868,13 +868,9 @@ void __init setup_arch(char **cmdline_p)
        cpu_init();
        tcm_init();
 
-       /*
-        * Set up various architecture-specific pointers
-        */
-       arch_nr_irqs = mdesc->nr_irqs;
-       init_arch_irq = mdesc->init_irq;
-       system_timer = mdesc->timer;
-       init_machine = mdesc->init_machine;
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+       handle_arch_irq = mdesc->handle_irq;
+#endif
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
@@ -884,6 +880,9 @@ void __init setup_arch(char **cmdline_p)
 #endif
 #endif
        early_trap_init();
+
+       if (mdesc->init_early)
+               mdesc->init_early();
 }
 
 
index bbca89872c18236a737c3ea8d963673821973676..4539ebcb089fad0c9471310aed633da450cf963f 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/irq.h>
 #include <linux/percpu.h>
 #include <linux/clockchips.h>
+#include <linux/completion.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
@@ -38,7 +39,6 @@
 #include <asm/tlbflush.h>
 #include <asm/ptrace.h>
 #include <asm/localtimer.h>
-#include <asm/smp_plat.h>
 
 /*
  * as from 2.5, kernels no longer have an init_tasks structure
  */
 struct secondary_data secondary_data;
 
-/*
- * structures for inter-processor calls
- * - A collection of single bit ipi messages.
- */
-struct ipi_data {
-       spinlock_t lock;
-       unsigned long ipi_count;
-       unsigned long bits;
-};
-
-static DEFINE_PER_CPU(struct ipi_data, ipi_data) = {
-       .lock   = SPIN_LOCK_UNLOCKED,
-};
-
 enum ipi_msg_type {
-       IPI_TIMER,
+       IPI_TIMER = 2,
        IPI_RESCHEDULE,
        IPI_CALL_FUNC,
        IPI_CALL_FUNC_SINGLE,
        IPI_CPU_STOP,
 };
 
-static inline void identity_mapping_add(pgd_t *pgd, unsigned long start,
-       unsigned long end)
-{
-       unsigned long addr, prot;
-       pmd_t *pmd;
-
-       prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
-       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
-               prot |= PMD_BIT4;
-
-       for (addr = start & PGDIR_MASK; addr < end;) {
-               pmd = pmd_offset(pgd + pgd_index(addr), addr);
-               pmd[0] = __pmd(addr | prot);
-               addr += SECTION_SIZE;
-               pmd[1] = __pmd(addr | prot);
-               addr += SECTION_SIZE;
-               flush_pmd_entry(pmd);
-               outer_clean_range(__pa(pmd), __pa(pmd + 1));
-       }
-}
-
-static inline void identity_mapping_del(pgd_t *pgd, unsigned long start,
-       unsigned long end)
-{
-       unsigned long addr;
-       pmd_t *pmd;
-
-       for (addr = start & PGDIR_MASK; addr < end; addr += PGDIR_SIZE) {
-               pmd = pmd_offset(pgd + pgd_index(addr), addr);
-               pmd[0] = __pmd(0);
-               pmd[1] = __pmd(0);
-               clean_pmd_entry(pmd);
-               outer_clean_range(__pa(pmd), __pa(pmd + 1));
-       }
-}
-
 int __cpuinit __cpu_up(unsigned int cpu)
 {
        struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu);
@@ -178,8 +128,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
                        barrier();
                }
 
-               if (!cpu_online(cpu))
+               if (!cpu_online(cpu)) {
+                       pr_crit("CPU%u: failed to come online\n", cpu);
                        ret = -EIO;
+               }
+       } else {
+               pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
        }
 
        secondary_data.stack = NULL;
@@ -195,18 +149,12 @@ int __cpuinit __cpu_up(unsigned int cpu)
 
        pgd_free(&init_mm, pgd);
 
-       if (ret) {
-               printk(KERN_CRIT "CPU%u: processor failed to boot\n", cpu);
-
-               /*
-                * FIXME: We need to clean up the new idle thread. --rmk
-                */
-       }
-
        return ret;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
+static void percpu_timer_stop(void);
+
 /*
  * __cpu_disable runs on the processor to be shutdown.
  */
@@ -234,7 +182,7 @@ int __cpu_disable(void)
        /*
         * Stop the local timer for this CPU.
         */
-       local_timer_stop();
+       percpu_timer_stop();
 
        /*
         * Flush user cache and TLB mappings, and then remove this CPU
@@ -253,12 +201,20 @@ int __cpu_disable(void)
        return 0;
 }
 
+static DECLARE_COMPLETION(cpu_died);
+
 /*
  * called on the thread which is asking for a CPU to be shutdown -
  * waits until shutdown has completed, or it is timed out.
  */
 void __cpu_die(unsigned int cpu)
 {
+       if (!wait_for_completion_timeout(&cpu_died, msecs_to_jiffies(5000))) {
+               pr_err("CPU%u: cpu didn't die\n", cpu);
+               return;
+       }
+       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
+
        if (!platform_cpu_kill(cpu))
                printk("CPU%u: unable to kill\n", cpu);
 }
@@ -275,12 +231,17 @@ void __ref cpu_die(void)
 {
        unsigned int cpu = smp_processor_id();
 
-       local_irq_disable();
        idle_task_exit();
 
+       local_irq_disable();
+       mb();
+
+       /* Tell __cpu_die() that this CPU is now safe to dispose of */
+       complete(&cpu_died);
+
        /*
         * actual CPU shutdown procedure is at least platform (if not
-        * CPU) specific
+        * CPU) specific.
         */
        platform_cpu_die(cpu);
 
@@ -290,12 +251,24 @@ void __ref cpu_die(void)
         * to be repeated to undo the effects of taking the CPU offline.
         */
        __asm__("mov    sp, %0\n"
+       "       mov     fp, #0\n"
        "       b       secondary_start_kernel"
                :
                : "r" (task_stack_page(current) + THREAD_SIZE - 8));
 }
 #endif /* CONFIG_HOTPLUG_CPU */
 
+/*
+ * Called by both boot and secondaries to move global data into
+ * per-processor storage.
+ */
+static void __cpuinit smp_store_cpu_info(unsigned int cpuid)
+{
+       struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
+
+       cpu_info->loops_per_jiffy = loops_per_jiffy;
+}
+
 /*
  * This is the secondary CPU boot entry.  We're using this CPUs
  * idle thread stack, but a set of temporary page tables.
@@ -311,7 +284,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
         * All kernel threads share the same mm context; grab a
         * reference and switch to it.
         */
-       atomic_inc(&mm->mm_users);
        atomic_inc(&mm->mm_count);
        current->active_mm = mm;
        cpumask_set_cpu(cpu, mm_cpumask(mm));
@@ -321,6 +293,7 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
 
        cpu_init();
        preempt_disable();
+       trace_hardirqs_off();
 
        /*
         * Give the platform a chance to do its own initialisation.
@@ -354,17 +327,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
        cpu_idle();
 }
 
-/*
- * Called by both boot and secondaries to move global data into
- * per-processor storage.
- */
-void __cpuinit smp_store_cpu_info(unsigned int cpuid)
-{
-       struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid);
-
-       cpu_info->loops_per_jiffy = loops_per_jiffy;
-}
-
 void __init smp_cpus_done(unsigned int max_cpus)
 {
        int cpu;
@@ -387,61 +349,80 @@ void __init smp_prepare_boot_cpu(void)
        per_cpu(cpu_data, cpu).idle = current;
 }
 
-static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg)
+void __init smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned long flags;
-       unsigned int cpu;
+       unsigned int ncores = num_possible_cpus();
 
-       local_irq_save(flags);
-
-       for_each_cpu(cpu, mask) {
-               struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
-
-               spin_lock(&ipi->lock);
-               ipi->bits |= 1 << msg;
-               spin_unlock(&ipi->lock);
-       }
+       smp_store_cpu_info(smp_processor_id());
 
        /*
-        * Call the platform specific cross-CPU call function.
+        * are we trying to boot more cores than exist?
         */
-       smp_cross_call(mask);
+       if (max_cpus > ncores)
+               max_cpus = ncores;
+
+       if (max_cpus > 1) {
+               /*
+                * Enable the local timer or broadcast device for the
+                * boot CPU, but only if we have more than one CPU.
+                */
+               percpu_timer_setup();
 
-       local_irq_restore(flags);
+               /*
+                * Initialise the SCU if there are more than one CPU
+                * and let them know where to start.
+                */
+               platform_smp_prepare_cpus(max_cpus);
+       }
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 {
-       send_ipi_message(mask, IPI_CALL_FUNC);
+       smp_cross_call(mask, IPI_CALL_FUNC);
 }
 
 void arch_send_call_function_single_ipi(int cpu)
 {
-       send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
+       smp_cross_call(cpumask_of(cpu), IPI_CALL_FUNC_SINGLE);
 }
 
-void show_ipi_list(struct seq_file *p)
+static const char *ipi_types[NR_IPI] = {
+#define S(x,s) [x - IPI_TIMER] = s
+       S(IPI_TIMER, "Timer broadcast interrupts"),
+       S(IPI_RESCHEDULE, "Rescheduling interrupts"),
+       S(IPI_CALL_FUNC, "Function call interrupts"),
+       S(IPI_CALL_FUNC_SINGLE, "Single function call interrupts"),
+       S(IPI_CPU_STOP, "CPU stop interrupts"),
+};
+
+void show_ipi_list(struct seq_file *p, int prec)
 {
-       unsigned int cpu;
+       unsigned int cpu, i;
 
-       seq_puts(p, "IPI:");
+       for (i = 0; i < NR_IPI; i++) {
+               seq_printf(p, "%*s%u: ", prec - 1, "IPI", i);
 
-       for_each_present_cpu(cpu)
-               seq_printf(p, " %10lu", per_cpu(ipi_data, cpu).ipi_count);
+               for_each_present_cpu(cpu)
+                       seq_printf(p, "%10u ",
+                                  __get_irq_stat(cpu, ipi_irqs[i]));
 
-       seq_putc(p, '\n');
+               seq_printf(p, " %s\n", ipi_types[i]);
+       }
 }
 
-void show_local_irqs(struct seq_file *p)
+u64 smp_irq_stat_cpu(unsigned int cpu)
 {
-       unsigned int cpu;
+       u64 sum = 0;
+       int i;
 
-       seq_printf(p, "LOC: ");
+       for (i = 0; i < NR_IPI; i++)
+               sum += __get_irq_stat(cpu, ipi_irqs[i]);
 
-       for_each_present_cpu(cpu)
-               seq_printf(p, "%10u ", irq_stat[cpu].local_timer_irqs);
+#ifdef CONFIG_LOCAL_TIMERS
+       sum += __get_irq_stat(cpu, local_timer_irqs);
+#endif
 
-       seq_putc(p, '\n');
+       return sum;
 }
 
 /*
@@ -464,18 +445,30 @@ asmlinkage void __exception_irq_entry do_local_timer(struct pt_regs *regs)
        int cpu = smp_processor_id();
 
        if (local_timer_ack()) {
-               irq_stat[cpu].local_timer_irqs++;
+               __inc_irq_stat(cpu, local_timer_irqs);
                ipi_timer();
        }
 
        set_irq_regs(old_regs);
 }
+
+void show_local_irqs(struct seq_file *p, int prec)
+{
+       unsigned int cpu;
+
+       seq_printf(p, "%*s: ", prec, "LOC");
+
+       for_each_present_cpu(cpu)
+               seq_printf(p, "%10u ", __get_irq_stat(cpu, local_timer_irqs));
+
+       seq_printf(p, " Local timer interrupts\n");
+}
 #endif
 
 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
 static void smp_timer_broadcast(const struct cpumask *mask)
 {
-       send_ipi_message(mask, IPI_TIMER);
+       smp_cross_call(mask, IPI_TIMER);
 }
 #else
 #define smp_timer_broadcast    NULL
@@ -512,6 +505,21 @@ void __cpuinit percpu_timer_setup(void)
        local_timer_setup(evt);
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * The generic clock events code purposely does not stop the local timer
+ * on CPU_DEAD/CPU_DEAD_FROZEN hotplug events, so we have to do it
+ * manually here.
+ */
+static void percpu_timer_stop(void)
+{
+       unsigned int cpu = smp_processor_id();
+       struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu);
+
+       evt->set_mode(CLOCK_EVT_MODE_UNUSED, evt);
+}
+#endif
+
 static DEFINE_SPINLOCK(stop_lock);
 
 /*
@@ -538,216 +546,76 @@ static void ipi_cpu_stop(unsigned int cpu)
 
 /*
  * Main handler for inter-processor interrupts
- *
- * For ARM, the ipimask now only identifies a single
- * category of IPI (Bit 1 IPIs have been replaced by a
- * different mechanism):
- *
- *  Bit 0 - Inter-processor function call
  */
-asmlinkage void __exception_irq_entry do_IPI(struct pt_regs *regs)
+asmlinkage void __exception_irq_entry do_IPI(int ipinr, struct pt_regs *regs)
 {
        unsigned int cpu = smp_processor_id();
-       struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
        struct pt_regs *old_regs = set_irq_regs(regs);
 
-       ipi->ipi_count++;
-
-       for (;;) {
-               unsigned long msgs;
-
-               spin_lock(&ipi->lock);
-               msgs = ipi->bits;
-               ipi->bits = 0;
-               spin_unlock(&ipi->lock);
+       if (ipinr >= IPI_TIMER && ipinr < IPI_TIMER + NR_IPI)
+               __inc_irq_stat(cpu, ipi_irqs[ipinr - IPI_TIMER]);
 
-               if (!msgs)
-                       break;
-
-               do {
-                       unsigned nextmsg;
-
-                       nextmsg = msgs & -msgs;
-                       msgs &= ~nextmsg;
-                       nextmsg = ffz(~nextmsg);
-
-                       switch (nextmsg) {
-                       case IPI_TIMER:
-                               ipi_timer();
-                               break;
+       switch (ipinr) {
+       case IPI_TIMER:
+               ipi_timer();
+               break;
 
-                       case IPI_RESCHEDULE:
-                               /*
-                                * nothing more to do - eveything is
-                                * done on the interrupt return path
-                                */
-                               break;
+       case IPI_RESCHEDULE:
+               /*
+                * nothing more to do - eveything is
+                * done on the interrupt return path
+                */
+               break;
 
-                       case IPI_CALL_FUNC:
-                               generic_smp_call_function_interrupt();
-                               break;
+       case IPI_CALL_FUNC:
+               generic_smp_call_function_interrupt();
+               break;
 
-                       case IPI_CALL_FUNC_SINGLE:
-                               generic_smp_call_function_single_interrupt();
-                               break;
+       case IPI_CALL_FUNC_SINGLE:
+               generic_smp_call_function_single_interrupt();
+               break;
 
-                       case IPI_CPU_STOP:
-                               ipi_cpu_stop(cpu);
-                               break;
+       case IPI_CPU_STOP:
+               ipi_cpu_stop(cpu);
+               break;
 
-                       default:
-                               printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
-                                      cpu, nextmsg);
-                               break;
-                       }
-               } while (msgs);
+       default:
+               printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
+                      cpu, ipinr);
+               break;
        }
-
        set_irq_regs(old_regs);
 }
 
 void smp_send_reschedule(int cpu)
 {
-       send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE);
+       smp_cross_call(cpumask_of(cpu), IPI_RESCHEDULE);
 }
 
 void smp_send_stop(void)
 {
-       cpumask_t mask = cpu_online_map;
-       cpu_clear(smp_processor_id(), mask);
-       if (!cpus_empty(mask))
-               send_ipi_message(&mask, IPI_CPU_STOP);
-}
+       unsigned long timeout;
 
-/*
- * not supported here
- */
-int setup_profiling_timer(unsigned int multiplier)
-{
-       return -EINVAL;
-}
+       if (num_online_cpus() > 1) {
+               cpumask_t mask = cpu_online_map;
+               cpu_clear(smp_processor_id(), mask);
 
-static void
-on_each_cpu_mask(void (*func)(void *), void *info, int wait,
-               const struct cpumask *mask)
-{
-       preempt_disable();
+               smp_cross_call(&mask, IPI_CPU_STOP);
+       }
 
-       smp_call_function_many(mask, func, info, wait);
-       if (cpumask_test_cpu(smp_processor_id(), mask))
-               func(info);
+       /* Wait up to one second for other CPUs to stop */
+       timeout = USEC_PER_SEC;
+       while (num_online_cpus() > 1 && timeout--)
+               udelay(1);
 
-       preempt_enable();
+       if (num_online_cpus() > 1)
+               pr_warning("SMP: failed to stop secondary CPUs\n");
 }
 
-/**********************************************************************/
-
 /*
- * TLB operations
+ * not supported here
  */
-struct tlb_args {
-       struct vm_area_struct *ta_vma;
-       unsigned long ta_start;
-       unsigned long ta_end;
-};
-
-static inline void ipi_flush_tlb_all(void *ignored)
-{
-       local_flush_tlb_all();
-}
-
-static inline void ipi_flush_tlb_mm(void *arg)
-{
-       struct mm_struct *mm = (struct mm_struct *)arg;
-
-       local_flush_tlb_mm(mm);
-}
-
-static inline void ipi_flush_tlb_page(void *arg)
-{
-       struct tlb_args *ta = (struct tlb_args *)arg;
-
-       local_flush_tlb_page(ta->ta_vma, ta->ta_start);
-}
-
-static inline void ipi_flush_tlb_kernel_page(void *arg)
-{
-       struct tlb_args *ta = (struct tlb_args *)arg;
-
-       local_flush_tlb_kernel_page(ta->ta_start);
-}
-
-static inline void ipi_flush_tlb_range(void *arg)
-{
-       struct tlb_args *ta = (struct tlb_args *)arg;
-
-       local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
-}
-
-static inline void ipi_flush_tlb_kernel_range(void *arg)
-{
-       struct tlb_args *ta = (struct tlb_args *)arg;
-
-       local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
-}
-
-void flush_tlb_all(void)
-{
-       if (tlb_ops_need_broadcast())
-               on_each_cpu(ipi_flush_tlb_all, NULL, 1);
-       else
-               local_flush_tlb_all();
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
-       if (tlb_ops_need_broadcast())
-               on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
-       else
-               local_flush_tlb_mm(mm);
-}
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
-{
-       if (tlb_ops_need_broadcast()) {
-               struct tlb_args ta;
-               ta.ta_vma = vma;
-               ta.ta_start = uaddr;
-               on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
-       } else
-               local_flush_tlb_page(vma, uaddr);
-}
-
-void flush_tlb_kernel_page(unsigned long kaddr)
-{
-       if (tlb_ops_need_broadcast()) {
-               struct tlb_args ta;
-               ta.ta_start = kaddr;
-               on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
-       } else
-               local_flush_tlb_kernel_page(kaddr);
-}
-
-void flush_tlb_range(struct vm_area_struct *vma,
-                     unsigned long start, unsigned long end)
-{
-       if (tlb_ops_need_broadcast()) {
-               struct tlb_args ta;
-               ta.ta_vma = vma;
-               ta.ta_start = start;
-               ta.ta_end = end;
-               on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm));
-       } else
-               local_flush_tlb_range(vma, start, end);
-}
-
-void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+int setup_profiling_timer(unsigned int multiplier)
 {
-       if (tlb_ops_need_broadcast()) {
-               struct tlb_args ta;
-               ta.ta_start = start;
-               ta.ta_end = end;
-               on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
-       } else
-               local_flush_tlb_kernel_range(start, end);
+       return -EINVAL;
 }
diff --git a/arch/arm/kernel/smp_tlb.c b/arch/arm/kernel/smp_tlb.c
new file mode 100644 (file)
index 0000000..7dcb352
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ *  linux/arch/arm/kernel/smp_tlb.c
+ *
+ *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/preempt.h>
+#include <linux/smp.h>
+
+#include <asm/smp_plat.h>
+#include <asm/tlbflush.h>
+
+static void on_each_cpu_mask(void (*func)(void *), void *info, int wait,
+       const struct cpumask *mask)
+{
+       preempt_disable();
+
+       smp_call_function_many(mask, func, info, wait);
+       if (cpumask_test_cpu(smp_processor_id(), mask))
+               func(info);
+
+       preempt_enable();
+}
+
+/**********************************************************************/
+
+/*
+ * TLB operations
+ */
+struct tlb_args {
+       struct vm_area_struct *ta_vma;
+       unsigned long ta_start;
+       unsigned long ta_end;
+};
+
+static inline void ipi_flush_tlb_all(void *ignored)
+{
+       local_flush_tlb_all();
+}
+
+static inline void ipi_flush_tlb_mm(void *arg)
+{
+       struct mm_struct *mm = (struct mm_struct *)arg;
+
+       local_flush_tlb_mm(mm);
+}
+
+static inline void ipi_flush_tlb_page(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_page(ta->ta_vma, ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_kernel_page(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_kernel_page(ta->ta_start);
+}
+
+static inline void ipi_flush_tlb_range(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_range(ta->ta_vma, ta->ta_start, ta->ta_end);
+}
+
+static inline void ipi_flush_tlb_kernel_range(void *arg)
+{
+       struct tlb_args *ta = (struct tlb_args *)arg;
+
+       local_flush_tlb_kernel_range(ta->ta_start, ta->ta_end);
+}
+
+void flush_tlb_all(void)
+{
+       if (tlb_ops_need_broadcast())
+               on_each_cpu(ipi_flush_tlb_all, NULL, 1);
+       else
+               local_flush_tlb_all();
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+       if (tlb_ops_need_broadcast())
+               on_each_cpu_mask(ipi_flush_tlb_mm, mm, 1, mm_cpumask(mm));
+       else
+               local_flush_tlb_mm(mm);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+       if (tlb_ops_need_broadcast()) {
+               struct tlb_args ta;
+               ta.ta_vma = vma;
+               ta.ta_start = uaddr;
+               on_each_cpu_mask(ipi_flush_tlb_page, &ta, 1, mm_cpumask(vma->vm_mm));
+       } else
+               local_flush_tlb_page(vma, uaddr);
+}
+
+void flush_tlb_kernel_page(unsigned long kaddr)
+{
+       if (tlb_ops_need_broadcast()) {
+               struct tlb_args ta;
+               ta.ta_start = kaddr;
+               on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
+       } else
+               local_flush_tlb_kernel_page(kaddr);
+}
+
+void flush_tlb_range(struct vm_area_struct *vma,
+                     unsigned long start, unsigned long end)
+{
+       if (tlb_ops_need_broadcast()) {
+               struct tlb_args ta;
+               ta.ta_vma = vma;
+               ta.ta_start = start;
+               ta.ta_end = end;
+               on_each_cpu_mask(ipi_flush_tlb_range, &ta, 1, mm_cpumask(vma->vm_mm));
+       } else
+               local_flush_tlb_range(vma, start, end);
+}
+
+void flush_tlb_kernel_range(unsigned long start, unsigned long end)
+{
+       if (tlb_ops_need_broadcast()) {
+               struct tlb_args ta;
+               ta.ta_start = start;
+               ta.ta_end = end;
+               on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
+       } else
+               local_flush_tlb_kernel_range(start, end);
+}
+
index 35882fbf37f90063723d3247352a3c05af480f99..dd790745b3ef7f1cabcba28d03c7e6acdbc6b2e4 100644 (file)
@@ -127,8 +127,6 @@ static void __cpuinit twd_calibrate_rate(void)
  */
 void __cpuinit twd_timer_setup(struct clock_event_device *clk)
 {
-       unsigned long flags;
-
        twd_calibrate_rate();
 
        clk->name = "local_timer";
@@ -143,20 +141,7 @@ void __cpuinit twd_timer_setup(struct clock_event_device *clk)
        clk->min_delta_ns = clockevent_delta2ns(0xf, clk);
 
        /* Make sure our local interrupt controller has this enabled */
-       local_irq_save(flags);
-       irq_to_desc(clk->irq)->status |= IRQ_NOPROBE;
-       get_irq_chip(clk->irq)->unmask(clk->irq);
-       local_irq_restore(flags);
+       gic_enable_ppi(clk->irq);
 
        clockevents_register_device(clk);
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
-/*
- * take a local timer down
- */
-void twd_timer_stop(void)
-{
-       __raw_writel(0, twd_base + TWD_TIMER_CONTROL);
-}
-#endif
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
new file mode 100644 (file)
index 0000000..7a57609
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ *  linux/arch/arm/kernel/swp_emulate.c
+ *
+ *  Copyright (C) 2009 ARM Limited
+ *  __user_* functions adapted from include/asm/uaccess.h
+ *
+ * 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.
+ *
+ *  Implements emulation of the SWP/SWPB instructions using load-exclusive and
+ *  store-exclusive for processors that have them disabled (or future ones that
+ *  might not implement them).
+ *
+ *  Syntax of SWP{B} instruction: SWP{B}<c> <Rt>, <Rt2>, [<Rn>]
+ *  Where: Rt  = destination
+ *        Rt2 = source
+ *        Rn  = address
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/syscalls.h>
+#include <linux/perf_event.h>
+
+#include <asm/traps.h>
+#include <asm/uaccess.h>
+
+/*
+ * Error-checking SWP macros implemented using ldrex{b}/strex{b}
+ */
+#define __user_swpX_asm(data, addr, res, temp, B)              \
+       __asm__ __volatile__(                                   \
+       "       mov             %2, %1\n"                       \
+       "0:     ldrex"B"        %1, [%3]\n"                     \
+       "1:     strex"B"        %0, %2, [%3]\n"                 \
+       "       cmp             %0, #0\n"                       \
+       "       movne           %0, %4\n"                       \
+       "2:\n"                                                  \
+       "       .section         .fixup,\"ax\"\n"               \
+       "       .align          2\n"                            \
+       "3:     mov             %0, %5\n"                       \
+       "       b               2b\n"                           \
+       "       .previous\n"                                    \
+       "       .section         __ex_table,\"a\"\n"            \
+       "       .align          3\n"                            \
+       "       .long           0b, 3b\n"                       \
+       "       .long           1b, 3b\n"                       \
+       "       .previous"                                      \
+       : "=&r" (res), "+r" (data), "=&r" (temp)                \
+       : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT)              \
+       : "cc", "memory")
+
+#define __user_swp_asm(data, addr, res, temp) \
+       __user_swpX_asm(data, addr, res, temp, "")
+#define __user_swpb_asm(data, addr, res, temp) \
+       __user_swpX_asm(data, addr, res, temp, "b")
+
+/*
+ * Macros/defines for extracting register numbers from instruction.
+ */
+#define EXTRACT_REG_NUM(instruction, offset) \
+       (((instruction) & (0xf << (offset))) >> (offset))
+#define RN_OFFSET  16
+#define RT_OFFSET  12
+#define RT2_OFFSET  0
+/*
+ * Bit 22 of the instruction encoding distinguishes between
+ * the SWP and SWPB variants (bit set means SWPB).
+ */
+#define TYPE_SWPB (1 << 22)
+
+static unsigned long swpcounter;
+static unsigned long swpbcounter;
+static unsigned long abtcounter;
+static pid_t         previous_pid;
+
+#ifdef CONFIG_PROC_FS
+static int proc_read_status(char *page, char **start, off_t off, int count,
+                           int *eof, void *data)
+{
+       char *p = page;
+       int len;
+
+       p += sprintf(p, "Emulated SWP:\t\t%lu\n", swpcounter);
+       p += sprintf(p, "Emulated SWPB:\t\t%lu\n", swpbcounter);
+       p += sprintf(p, "Aborted SWP{B}:\t\t%lu\n", abtcounter);
+       if (previous_pid != 0)
+               p += sprintf(p, "Last process:\t\t%d\n", previous_pid);
+
+       len = (p - page) - off;
+       if (len < 0)
+               len = 0;
+
+       *eof = (len <= count) ? 1 : 0;
+       *start = page + off;
+
+       return len;
+}
+#endif
+
+/*
+ * Set up process info to signal segmentation fault - called on access error.
+ */
+static void set_segfault(struct pt_regs *regs, unsigned long addr)
+{
+       siginfo_t info;
+
+       if (find_vma(current->mm, addr) == NULL)
+               info.si_code = SEGV_MAPERR;
+       else
+               info.si_code = SEGV_ACCERR;
+
+       info.si_signo = SIGSEGV;
+       info.si_errno = 0;
+       info.si_addr  = (void *) instruction_pointer(regs);
+
+       pr_debug("SWP{B} emulation: access caused memory abort!\n");
+       arm_notify_die("Illegal memory access", regs, &info, 0, 0);
+
+       abtcounter++;
+}
+
+static int emulate_swpX(unsigned int address, unsigned int *data,
+                       unsigned int type)
+{
+       unsigned int res = 0;
+
+       if ((type != TYPE_SWPB) && (address & 0x3)) {
+               /* SWP to unaligned address not permitted */
+               pr_debug("SWP instruction on unaligned pointer!\n");
+               return -EFAULT;
+       }
+
+       while (1) {
+               unsigned long temp;
+
+               /*
+                * Barrier required between accessing protected resource and
+                * releasing a lock for it. Legacy code might not have done
+                * this, and we cannot determine that this is not the case
+                * being emulated, so insert always.
+                */
+               smp_mb();
+
+               if (type == TYPE_SWPB)
+                       __user_swpb_asm(*data, address, res, temp);
+               else
+                       __user_swp_asm(*data, address, res, temp);
+
+               if (likely(res != -EAGAIN) || signal_pending(current))
+                       break;
+
+               cond_resched();
+       }
+
+       if (res == 0) {
+               /*
+                * Barrier also required between aquiring a lock for a
+                * protected resource and accessing the resource. Inserted for
+                * same reason as above.
+                */
+               smp_mb();
+
+               if (type == TYPE_SWPB)
+                       swpbcounter++;
+               else
+                       swpcounter++;
+       }
+
+       return res;
+}
+
+/*
+ * swp_handler logs the id of calling process, dissects the instruction, sanity
+ * checks the memory location, calls emulate_swpX for the actual operation and
+ * deals with fixup/error handling before returning
+ */
+static int swp_handler(struct pt_regs *regs, unsigned int instr)
+{
+       unsigned int address, destreg, data, type;
+       unsigned int res = 0;
+
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, 0, regs, regs->ARM_pc);
+
+       if (current->pid != previous_pid) {
+               pr_debug("\"%s\" (%ld) uses deprecated SWP{B} instruction\n",
+                        current->comm, (unsigned long)current->pid);
+               previous_pid = current->pid;
+       }
+
+       address = regs->uregs[EXTRACT_REG_NUM(instr, RN_OFFSET)];
+       data    = regs->uregs[EXTRACT_REG_NUM(instr, RT2_OFFSET)];
+       destreg = EXTRACT_REG_NUM(instr, RT_OFFSET);
+
+       type = instr & TYPE_SWPB;
+
+       pr_debug("addr in r%d->0x%08x, dest is r%d, source in r%d->0x%08x)\n",
+                EXTRACT_REG_NUM(instr, RN_OFFSET), address,
+                destreg, EXTRACT_REG_NUM(instr, RT2_OFFSET), data);
+
+       /* Check access in reasonable access range for both SWP and SWPB */
+       if (!access_ok(VERIFY_WRITE, (address & ~3), 4)) {
+               pr_debug("SWP{B} emulation: access to %p not allowed!\n",
+                        (void *)address);
+               res = -EFAULT;
+       } else {
+               res = emulate_swpX(address, &data, type);
+       }
+
+       if (res == 0) {
+               /*
+                * On successful emulation, revert the adjustment to the PC
+                * made in kernel/traps.c in order to resume execution at the
+                * instruction following the SWP{B}.
+                */
+               regs->ARM_pc += 4;
+               regs->uregs[destreg] = data;
+       } else if (res == -EFAULT) {
+               /*
+                * Memory errors do not mean emulation failed.
+                * Set up signal info to return SEGV, then return OK
+                */
+               set_segfault(regs, address);
+       }
+
+       return 0;
+}
+
+/*
+ * Only emulate SWP/SWPB executed in ARM state/User mode.
+ * The kernel must be SWP free and SWP{B} does not exist in Thumb/ThumbEE.
+ */
+static struct undef_hook swp_hook = {
+       .instr_mask = 0x0fb00ff0,
+       .instr_val  = 0x01000090,
+       .cpsr_mask  = MODE_MASK | PSR_T_BIT | PSR_J_BIT,
+       .cpsr_val   = USR_MODE,
+       .fn         = swp_handler
+};
+
+/*
+ * Register handler and create status file in /proc/cpu
+ * Invoked as late_initcall, since not needed before init spawned.
+ */
+static int __init swp_emulation_init(void)
+{
+#ifdef CONFIG_PROC_FS
+       struct proc_dir_entry *res;
+
+       res = create_proc_entry("cpu/swp_emulation", S_IRUGO, NULL);
+
+       if (!res)
+               return -ENOMEM;
+
+       res->read_proc = proc_read_status;
+#endif /* CONFIG_PROC_FS */
+
+       printk(KERN_NOTICE "Registering SWP/SWPB emulation handler\n");
+       register_undef_hook(&swp_hook);
+
+       return 0;
+}
+
+late_initcall(swp_emulation_init);
index 38c261f9951c8ddf5be050e61743dfe449f887bb..f1e2eb19a67d40b9fd71166da0e46c21be72e124 100644 (file)
 #include <asm/leds.h>
 #include <asm/thread_info.h>
 #include <asm/stacktrace.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
 /*
  * Our system timer.
  */
-struct sys_timer *system_timer;
+static struct sys_timer *system_timer;
 
 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE)
 /* this needs a better home */
@@ -160,6 +161,7 @@ device_initcall(timer_init_sysfs);
 
 void __init time_init(void)
 {
+       system_timer = machine_desc->timer;
        system_timer->init();
 }
 
index 446aee97436f22b82ba7d2f16a06d74b507b7042..ee57640ba2bb50ddff8400cccfb6c01603a0da87 100644 (file)
@@ -37,6 +37,8 @@
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
 
+void *vectors_page;
+
 #ifdef CONFIG_DEBUG_USER
 unsigned int user_debug;
 
@@ -708,19 +710,19 @@ void __readwrite_bug(const char *fn)
 }
 EXPORT_SYMBOL(__readwrite_bug);
 
-void __pte_error(const char *file, int line, unsigned long val)
+void __pte_error(const char *file, int line, pte_t pte)
 {
-       printk("%s:%d: bad pte %08lx.\n", file, line, val);
+       printk("%s:%d: bad pte %08lx.\n", file, line, pte_val(pte));
 }
 
-void __pmd_error(const char *file, int line, unsigned long val)
+void __pmd_error(const char *file, int line, pmd_t pmd)
 {
-       printk("%s:%d: bad pmd %08lx.\n", file, line, val);
+       printk("%s:%d: bad pmd %08lx.\n", file, line, pmd_val(pmd));
 }
 
-void __pgd_error(const char *file, int line, unsigned long val)
+void __pgd_error(const char *file, int line, pgd_t pgd)
 {
-       printk("%s:%d: bad pgd %08lx.\n", file, line, val);
+       printk("%s:%d: bad pgd %08lx.\n", file, line, pgd_val(pgd));
 }
 
 asmlinkage void __div0(void)
@@ -756,7 +758,11 @@ static void __init kuser_get_tls_init(unsigned long vectors)
 
 void __init early_trap_init(void)
 {
+#if defined(CONFIG_CPU_USE_DOMAINS)
        unsigned long vectors = CONFIG_VECTORS_BASE;
+#else
+       unsigned long vectors = (unsigned long)vectors_page;
+#endif
        extern char __stubs_start[], __stubs_end[];
        extern char __vectors_start[], __vectors_end[];
        extern char __kuser_helper_start[], __kuser_helper_end[];
@@ -780,10 +786,10 @@ void __init early_trap_init(void)
         * Copy signal return handlers into the vector page, and
         * set sigreturn to be a pointer to these.
         */
-       memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes,
-              sizeof(sigreturn_codes));
-       memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
-              sizeof(syscall_restart_code));
+       memcpy((void *)(vectors + KERN_SIGRETURN_CODE - CONFIG_VECTORS_BASE),
+              sigreturn_codes, sizeof(sigreturn_codes));
+       memcpy((void *)(vectors + KERN_RESTART_CODE - CONFIG_VECTORS_BASE),
+              syscall_restart_code, sizeof(syscall_restart_code));
 
        flush_icache_range(vectors, vectors + PAGE_SIZE);
        modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
index 897c1a8f16942e179c9d42e3f4dd935542078762..86b66f3f203187c2b8f0bed5ec7ff096ca656967 100644 (file)
@@ -168,6 +168,7 @@ SECTIONS
 
                NOSAVE_DATA
                CACHELINE_ALIGNED_DATA(32)
+               READ_MOSTLY_DATA(32)
 
                /*
                 * The exception fixup table (might need resorting at runtime)
index b1631a7dbe750dc4615e8d76f535e48fb2a0c52d..1b049cd7a49a8badab511ed2b0532d1f7e76b733 100644 (file)
  */
 #include <linux/linkage.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 ENTRY(__get_user_1)
-1:     ldrbt   r2, [r0]
+1:     T(ldrb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_1)
 
 ENTRY(__get_user_2)
 #ifdef CONFIG_THUMB2_KERNEL
-2:     ldrbt   r2, [r0]
-3:     ldrbt   r3, [r0, #1]
+2:     T(ldrb) r2, [r0]
+3:     T(ldrb) r3, [r0, #1]
 #else
-2:     ldrbt   r2, [r0], #1
-3:     ldrbt   r3, [r0]
+2:     T(ldrb) r2, [r0], #1
+3:     T(ldrb) r3, [r0]
 #endif
 #ifndef __ARMEB__
        orr     r2, r2, r3, lsl #8
@@ -53,7 +54,7 @@ ENTRY(__get_user_2)
 ENDPROC(__get_user_2)
 
 ENTRY(__get_user_4)
-4:     ldrt    r2, [r0]
+4:     T(ldr)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_4)
index 5a01a23c6c06f8315a571e93dde34a18dc744591..c023fc11e86c7b603eaaa08270e7ea429ecfab5f 100644 (file)
  */
 #include <linux/linkage.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
 ENTRY(__put_user_1)
-1:     strbt   r2, [r0]
+1:     T(strb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_1)
@@ -39,19 +40,19 @@ ENTRY(__put_user_2)
        mov     ip, r2, lsr #8
 #ifdef CONFIG_THUMB2_KERNEL
 #ifndef __ARMEB__
-2:     strbt   r2, [r0]
-3:     strbt   ip, [r0, #1]
+2:     T(strb) r2, [r0]
+3:     T(strb) ip, [r0, #1]
 #else
-2:     strbt   ip, [r0]
-3:     strbt   r2, [r0, #1]
+2:     T(strb) ip, [r0]
+3:     T(strb) r2, [r0, #1]
 #endif
 #else  /* !CONFIG_THUMB2_KERNEL */
 #ifndef __ARMEB__
-2:     strbt   r2, [r0], #1
-3:     strbt   ip, [r0]
+2:     T(strb) r2, [r0], #1
+3:     T(strb) ip, [r0]
 #else
-2:     strbt   ip, [r0], #1
-3:     strbt   r2, [r0]
+2:     T(strb) ip, [r0], #1
+3:     T(strb) r2, [r0]
 #endif
 #endif /* CONFIG_THUMB2_KERNEL */
        mov     r0, #0
@@ -59,18 +60,18 @@ ENTRY(__put_user_2)
 ENDPROC(__put_user_2)
 
 ENTRY(__put_user_4)
-4:     strt    r2, [r0]
+4:     T(str)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_4)
 
 ENTRY(__put_user_8)
 #ifdef CONFIG_THUMB2_KERNEL
-5:     strt    r2, [r0]
-6:     strt    r3, [r0, #4]
+5:     T(str)  r2, [r0]
+6:     T(str)  r3, [r0, #4]
 #else
-5:     strt    r2, [r0], #4
-6:     strt    r3, [r0]
+5:     T(str)  r2, [r0], #4
+6:     T(str)  r3, [r0]
 #endif
        mov     r0, #0
        mov     pc, lr
index fee9f6f88adb5eddf11f78ac8345423256381757..d0ece2aeb70dfc380d689a85a141a28a5917ec20 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/errno.h>
+#include <asm/domain.h>
 
                .text
 
                rsb     ip, ip, #4
                cmp     ip, #2
                ldrb    r3, [r1], #1
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                ldrgtb  r3, [r1], #1
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                sub     r2, r2, ip
                b       .Lc2u_dest_aligned
 
@@ -58,7 +59,7 @@ ENTRY(__copy_to_user)
                addmi   ip, r2, #4
                bmi     .Lc2u_0nowords
                ldr     r3, [r1], #4
-USER(          strt    r3, [r0], #4)                   @ May fault
+USER(          T(str)  r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT    @ On each page, use a ld/st??t instruction
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -87,18 +88,18 @@ USER(               strt    r3, [r0], #4)                   @ May fault
                stmneia r0!, {r3 - r4}                  @ Shouldnt fault
                tst     ip, #4
                ldrne   r3, [r1], #4
-               strnet  r3, [r0], #4                    @ Shouldnt fault
+               T(strne) r3, [r0], #4                   @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_0fupi
 .Lc2u_0nowords:        teq     ip, #0
                beq     .Lc2u_finished
 .Lc2u_nowords: cmp     ip, #2
                ldrb    r3, [r1], #1
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                ldrgtb  r3, [r1], #1
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                b       .Lc2u_finished
 
 .Lc2u_not_enough:
@@ -119,7 +120,7 @@ USER(               strgtbt r3, [r0], #1)                   @ May fault
                mov     r3, r7, pull #8
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #24
-USER(          strt    r3, [r0], #4)                   @ May fault
+USER(          T(str)  r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -154,18 +155,18 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #8
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #24
-               strnet  r3, [r0], #4                    @ Shouldnt fault
+               T(strne) r3, [r0], #4                   @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_1fupi
 .Lc2u_1nowords:        mov     r3, r7, get_byte_1
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                movge   r3, r7, get_byte_2
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                movgt   r3, r7, get_byte_3
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                b       .Lc2u_finished
 
 .Lc2u_2fupi:   subs    r2, r2, #4
@@ -174,7 +175,7 @@ USER(               strgtbt r3, [r0], #1)                   @ May fault
                mov     r3, r7, pull #16
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #16
-USER(          strt    r3, [r0], #4)                   @ May fault
+USER(          T(str)  r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -209,18 +210,18 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #16
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #16
-               strnet  r3, [r0], #4                    @ Shouldnt fault
+               T(strne) r3, [r0], #4                   @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_2fupi
 .Lc2u_2nowords:        mov     r3, r7, get_byte_2
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                movge   r3, r7, get_byte_3
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                ldrgtb  r3, [r1], #0
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                b       .Lc2u_finished
 
 .Lc2u_3fupi:   subs    r2, r2, #4
@@ -229,7 +230,7 @@ USER(               strgtbt r3, [r0], #1)                   @ May fault
                mov     r3, r7, pull #24
                ldr     r7, [r1], #4
                orr     r3, r3, r7, push #8
-USER(          strt    r3, [r0], #4)                   @ May fault
+USER(          T(str)  r3, [r0], #4)                   @ May fault
                mov     ip, r0, lsl #32 - PAGE_SHIFT
                rsb     ip, ip, #0
                movs    ip, ip, lsr #32 - PAGE_SHIFT
@@ -264,18 +265,18 @@ USER(             strt    r3, [r0], #4)                   @ May fault
                movne   r3, r7, pull #24
                ldrne   r7, [r1], #4
                orrne   r3, r3, r7, push #8
-               strnet  r3, [r0], #4                    @ Shouldnt fault
+               T(strne) r3, [r0], #4                   @ Shouldnt fault
                ands    ip, ip, #3
                beq     .Lc2u_3fupi
 .Lc2u_3nowords:        mov     r3, r7, get_byte_3
                teq     ip, #0
                beq     .Lc2u_finished
                cmp     ip, #2
-USER(          strbt   r3, [r0], #1)                   @ May fault
+USER(          T(strb) r3, [r0], #1)                   @ May fault
                ldrgeb  r3, [r1], #1
-USER(          strgebt r3, [r0], #1)                   @ May fault
+USER(          T(strgeb) r3, [r0], #1)                 @ May fault
                ldrgtb  r3, [r1], #0
-USER(          strgtbt r3, [r0], #1)                   @ May fault
+USER(          T(strgtb) r3, [r0], #1)                 @ May fault
                b       .Lc2u_finished
 ENDPROC(__copy_to_user)
 
@@ -294,11 +295,11 @@ ENDPROC(__copy_to_user)
 .Lcfu_dest_not_aligned:
                rsb     ip, ip, #4
                cmp     ip, #2
-USER(          ldrbt   r3, [r1], #1)                   @ May fault
+USER(          T(ldrb) r3, [r1], #1)                   @ May fault
                strb    r3, [r0], #1
-USER(          ldrgebt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
                strgeb  r3, [r0], #1
-USER(          ldrgtbt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
                strgtb  r3, [r0], #1
                sub     r2, r2, ip
                b       .Lcfu_dest_aligned
@@ -321,7 +322,7 @@ ENTRY(__copy_from_user)
 .Lcfu_0fupi:   subs    r2, r2, #4
                addmi   ip, r2, #4
                bmi     .Lcfu_0nowords
-USER(          ldrt    r3, [r1], #4)
+USER(          T(ldr)  r3, [r1], #4)
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT    @ On each page, use a ld/st??t instruction
                rsb     ip, ip, #0
@@ -350,18 +351,18 @@ USER(             ldrt    r3, [r1], #4)
                ldmneia r1!, {r3 - r4}                  @ Shouldnt fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
-               ldrnet  r3, [r1], #4                    @ Shouldnt fault
+               T(ldrne) r3, [r1], #4                   @ Shouldnt fault
                strne   r3, [r0], #4
                ands    ip, ip, #3
                beq     .Lcfu_0fupi
 .Lcfu_0nowords:        teq     ip, #0
                beq     .Lcfu_finished
 .Lcfu_nowords: cmp     ip, #2
-USER(          ldrbt   r3, [r1], #1)                   @ May fault
+USER(          T(ldrb) r3, [r1], #1)                   @ May fault
                strb    r3, [r0], #1
-USER(          ldrgebt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
                strgeb  r3, [r0], #1
-USER(          ldrgtbt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 
@@ -374,7 +375,7 @@ USER(               ldrgtbt r3, [r1], #1)                   @ May fault
 
 .Lcfu_src_not_aligned:
                bic     r1, r1, #3
-USER(          ldrt    r7, [r1], #4)                   @ May fault
+USER(          T(ldr)  r7, [r1], #4)                   @ May fault
                cmp     ip, #2
                bgt     .Lcfu_3fupi
                beq     .Lcfu_2fupi
@@ -382,7 +383,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_1nowords
                mov     r3, r7, pull #8
-USER(          ldrt    r7, [r1], #4)                   @ May fault
+USER(          T(ldr)  r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #24
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -417,7 +418,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #8
-USER(          ldrnet  r7, [r1], #4)                   @ May fault
+USER(          T(ldrne) r7, [r1], #4)                  @ May fault
                orrne   r3, r3, r7, push #24
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -437,7 +438,7 @@ USER(               ldrnet  r7, [r1], #4)                   @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_2nowords
                mov     r3, r7, pull #16
-USER(          ldrt    r7, [r1], #4)                   @ May fault
+USER(          T(ldr)  r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #16
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -473,7 +474,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #16
-USER(          ldrnet  r7, [r1], #4)                   @ May fault
+USER(          T(ldrne) r7, [r1], #4)                  @ May fault
                orrne   r3, r3, r7, push #16
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -485,7 +486,7 @@ USER(               ldrnet  r7, [r1], #4)                   @ May fault
                strb    r3, [r0], #1
                movge   r3, r7, get_byte_3
                strgeb  r3, [r0], #1
-USER(          ldrgtbt r3, [r1], #0)                   @ May fault
+USER(          T(ldrgtb) r3, [r1], #0)                 @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 
@@ -493,7 +494,7 @@ USER(               ldrgtbt r3, [r1], #0)                   @ May fault
                addmi   ip, r2, #4
                bmi     .Lcfu_3nowords
                mov     r3, r7, pull #24
-USER(          ldrt    r7, [r1], #4)                   @ May fault
+USER(          T(ldr)  r7, [r1], #4)                   @ May fault
                orr     r3, r3, r7, push #8
                str     r3, [r0], #4
                mov     ip, r1, lsl #32 - PAGE_SHIFT
@@ -528,7 +529,7 @@ USER(               ldrt    r7, [r1], #4)                   @ May fault
                stmneia r0!, {r3 - r4}
                tst     ip, #4
                movne   r3, r7, pull #24
-USER(          ldrnet  r7, [r1], #4)                   @ May fault
+USER(          T(ldrne) r7, [r1], #4)                  @ May fault
                orrne   r3, r3, r7, push #8
                strne   r3, [r0], #4
                ands    ip, ip, #3
@@ -538,9 +539,9 @@ USER(               ldrnet  r7, [r1], #4)                   @ May fault
                beq     .Lcfu_finished
                cmp     ip, #2
                strb    r3, [r0], #1
-USER(          ldrgebt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgeb) r3, [r1], #1)                 @ May fault
                strgeb  r3, [r0], #1
-USER(          ldrgtbt r3, [r1], #1)                   @ May fault
+USER(          T(ldrgtb) r3, [r1], #1)                 @ May fault
                strgtb  r3, [r0], #1
                b       .Lcfu_finished
 ENDPROC(__copy_from_user)
index 62d686f0b42602e6b1f7beb096524944452b3b45..d13add71f72accab27ae6abade209d8fad2259f9 100644 (file)
@@ -65,7 +65,7 @@ obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o
 obj-$(CONFIG_MACH_CPU9G20)     += board-cpu9krea.o
 obj-$(CONFIG_MACH_STAMP9G20)   += board-stamp9g20.o
 obj-$(CONFIG_MACH_PORTUXG20)   += board-stamp9g20.o
-obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o
+obj-$(CONFIG_MACH_PCONTROL_G20)        += board-pcontrol-g20.o board-stamp9g20.o
 
 # AT91SAM9260/AT91SAM9G20 board-specific support
 obj-$(CONFIG_MACH_SNAPPER_9260)        += board-snapper9260.o
index 2500f41d8d2dba517e4cf1d72cf1af225a765d6a..1dd69c85dfecc4c3583bd9cc511a675b3376bf45 100644 (file)
@@ -101,7 +101,6 @@ static struct clocksource clk32k = {
        .rating         = 150,
        .read           = read_clk32k,
        .mask           = CLOCKSOURCE_MASK(20),
-       .shift          = 10,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -201,8 +200,7 @@ void __init at91rm9200_timer_init(void)
        clockevents_register_device(&clkevt);
 
        /* register clocksource */
-       clk32k.mult = clocksource_hz2mult(AT91_SLOW_CLOCK, clk32k.shift);
-       clocksource_register(&clk32k);
+       clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
 }
 
 struct sys_timer at91rm9200_timer = {
index 608a63240b64ba9944f511ea9c48879d7878fb08..4ba85499fa979b8503b2e86ab9aa5c2786266b1c 100644 (file)
@@ -51,7 +51,6 @@ static struct clocksource pit_clk = {
        .name           = "pit",
        .rating         = 175,
        .read           = read_pit_clk,
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -163,10 +162,9 @@ static void __init at91sam926x_pit_init(void)
         * Register clocksource.  The high order bits of PIV are unused,
         * so this isn't a 32-bit counter unless we get clockevent irqs.
         */
-       pit_clk.mult = clocksource_hz2mult(pit_rate, pit_clk.shift);
        bits = 12 /* PICNT */ + ilog2(pit_cycle) /* PIV */;
        pit_clk.mask = CLOCKSOURCE_MASK(bits);
-       clocksource_register(&pit_clk);
+       clocksource_register_hz(&pit_clk, pit_rate);
 
        /* Set up irq handler */
        setup_irq(AT91_ID_SYS, &at91sam926x_pit_irq);
index bba5a560e02b8c829304ffdded29038760167cdd..feb65787c30be5502985a112e4b200d0f7de8ac0 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <mach/board.h>
 #include <mach/at91sam9_smc.h>
+#include <mach/stamp9g20.h>
 
 #include "sam9_smc.h"
 #include "generic.h"
 
 static void __init pcontrol_g20_map_io(void)
 {
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx, Tx) only TTL -> JTAG connector X7 17,19 ) */
-       at91_register_uart(0, 0, 0);
+       stamp9g20_map_io();
 
        /* USART0 on ttyS1. (Rx, Tx, CTS, RTS) piggyback  A2 */
        at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS
@@ -54,9 +51,6 @@ static void __init pcontrol_g20_map_io(void)
 
        /* USART2 on ttyS3. (Rx, Tx)  9bit-Bus  Multidrop-mode  X4 */
        at91_register_uart(AT91SAM9260_ID_US4, 3, 0);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
 }
 
 
@@ -66,38 +60,6 @@ static void __init init_irq(void)
 }
 
 
-/*
- * NAND flash 512MiB 1,8V 8-bit, sector size 128 KiB
- */
-static struct atmel_nand_data __initdata nand_data = {
-       .ale            = 21,
-       .cle            = 22,
-       .rdy_pin        = AT91_PIN_PC13,
-       .enable_pin     = AT91_PIN_PC14,
-};
-
-/*
- * Bus timings; unit = 7.57ns
- */
-static struct sam9_smc_config __initdata nand_smc_config = {
-       .ncs_read_setup         = 0,
-       .nrd_setup              = 2,
-       .ncs_write_setup        = 0,
-       .nwe_setup              = 2,
-
-       .ncs_read_pulse         = 4,
-       .nrd_pulse              = 4,
-       .ncs_write_pulse        = 4,
-       .nwe_pulse              = 4,
-
-       .read_cycle             = 7,
-       .write_cycle            = 7,
-
-       .mode                   = AT91_SMC_READMODE | AT91_SMC_WRITEMODE
-                       | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8,
-       .tdf_cycles             = 3,
-};
-
 static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .ncs_read_setup         = 16,
        .nrd_setup              = 18,
@@ -138,14 +100,6 @@ static struct sam9_smc_config __initdata pcontrol_smc_config[2] = { {
        .tdf_cycles             = 1,
 } };
 
-static void __init add_device_nand(void)
-{
-       /* configure chip-select 3 (NAND) */
-       sam9_smc_configure(3, &nand_smc_config);
-       at91_add_device_nand(&nand_data);
-}
-
-
 static void __init add_device_pcontrol(void)
 {
        /* configure chip-select 4 (IO compatible to 8051  X4 ) */
@@ -155,23 +109,6 @@ static void __init add_device_pcontrol(void)
 }
 
 
-/*
- * MCI (SD/MMC)
- * det_pin, wp_pin and vcc_pin are not connected
- */
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-static struct mci_platform_data __initdata mmc_data = {
-       .slot[0] = {
-               .bus_width      = 4,
-       },
-};
-#else
-static struct at91_mmc_data __initdata mmc_data = {
-       .wire4          = 1,
-};
-#endif
-
-
 /*
  * USB Host port
  */
@@ -265,42 +202,13 @@ static struct spi_board_info pcontrol_g20_spi_devices[] = {
 };
 
 
-/*
- * Dallas 1-Wire  DS2431
- */
-static struct w1_gpio_platform_data w1_gpio_pdata = {
-       .pin            = AT91_PIN_PA29,
-       .is_open_drain  = 1,
-};
-
-static struct platform_device w1_device = {
-       .name                   = "w1-gpio",
-       .id                     = -1,
-       .dev.platform_data      = &w1_gpio_pdata,
-};
-
-static void add_wire1(void)
-{
-       at91_set_GPIO_periph(w1_gpio_pdata.pin, 1);
-       at91_set_multi_drive(w1_gpio_pdata.pin, 1);
-       platform_device_register(&w1_device);
-}
-
-
 static void __init pcontrol_g20_board_init(void)
 {
-       at91_add_device_serial();
-       add_device_nand();
-#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE)
-       at91_add_device_mci(0, &mmc_data);
-#else
-       at91_add_device_mmc(0, &mmc_data);
-#endif
+       stamp9g20_board_init();
        at91_add_device_usbh(&usbh_data);
        at91_add_device_eth(&macb_data);
        at91_add_device_i2c(pcontrol_g20_i2c_devices,
                ARRAY_SIZE(pcontrol_g20_i2c_devices));
-       add_wire1();
        add_device_pcontrol();
        at91_add_device_spi(pcontrol_g20_spi_devices,
                ARRAY_SIZE(pcontrol_g20_spi_devices));
index 5206eef4a67eba12e1b22bd7ae0faa48ce29271a..f8902b118960d84f4d9bf6c57d3a28e9c302df64 100644 (file)
@@ -32,7 +32,7 @@
 #include "generic.h"
 
 
-static void __init portuxg20_map_io(void)
+void __init stamp9g20_map_io(void)
 {
        /* Initialize processor: 18.432 MHz crystal */
        at91sam9260_initialize(18432000);
@@ -40,6 +40,24 @@ static void __init portuxg20_map_io(void)
        /* DGBU on ttyS0. (Rx & Tx only) */
        at91_register_uart(0, 0, 0);
 
+       /* set serial console to ttyS0 (ie, DBGU) */
+       at91_set_serial_console(0);
+}
+
+static void __init stamp9g20evb_map_io(void)
+{
+       stamp9g20_map_io();
+
+       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
+       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
+                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
+                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
+}
+
+static void __init portuxg20_map_io(void)
+{
+       stamp9g20_map_io();
+
        /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
        at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
                                                | ATMEL_UART_DTR | ATMEL_UART_DSR
@@ -56,26 +74,6 @@ static void __init portuxg20_map_io(void)
 
        /* USART5 on ttyS6. (Rx, Tx only) */
        at91_register_uart(AT91SAM9260_ID_US5, 6, 0);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
-}
-
-static void __init stamp9g20_map_io(void)
-{
-       /* Initialize processor: 18.432 MHz crystal */
-       at91sam9260_initialize(18432000);
-
-       /* DGBU on ttyS0. (Rx & Tx only) */
-       at91_register_uart(0, 0, 0);
-
-       /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */
-       at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS
-                                               | ATMEL_UART_DTR | ATMEL_UART_DSR
-                                               | ATMEL_UART_DCD | ATMEL_UART_RI);
-
-       /* set serial console to ttyS0 (ie, DBGU) */
-       at91_set_serial_console(0);
 }
 
 static void __init init_irq(void)
@@ -156,7 +154,7 @@ static struct at91_udc_data __initdata portuxg20_udc_data = {
        .pullup_pin     = 0,            /* pull-up driven by UDC */
 };
 
-static struct at91_udc_data __initdata stamp9g20_udc_data = {
+static struct at91_udc_data __initdata stamp9g20evb_udc_data = {
        .vbus_pin       = AT91_PIN_PA22,
        .pullup_pin     = 0,            /* pull-up driven by UDC */
 };
@@ -190,7 +188,7 @@ static struct gpio_led portuxg20_leds[] = {
        }
 };
 
-static struct gpio_led stamp9g20_leds[] = {
+static struct gpio_led stamp9g20evb_leds[] = {
        {
                .name                   = "D8",
                .gpio                   = AT91_PIN_PB18,
@@ -250,7 +248,7 @@ void add_w1(void)
 }
 
 
-static void __init generic_board_init(void)
+void __init stamp9g20_board_init(void)
 {
        /* Serial */
        at91_add_device_serial();
@@ -262,34 +260,40 @@ static void __init generic_board_init(void)
 #else
        at91_add_device_mmc(0, &mmc_data);
 #endif
-       /* USB Host */
-       at91_add_device_usbh(&usbh_data);
-       /* Ethernet */
-       at91_add_device_eth(&macb_data);
-       /* I2C */
-       at91_add_device_i2c(NULL, 0);
        /* W1 */
        add_w1();
 }
 
 static void __init portuxg20_board_init(void)
 {
-       generic_board_init();
-       /* SPI */
-       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
+       stamp9g20_board_init();
+       /* USB Host */
+       at91_add_device_usbh(&usbh_data);
        /* USB Device */
        at91_add_device_udc(&portuxg20_udc_data);
+       /* Ethernet */
+       at91_add_device_eth(&macb_data);
+       /* I2C */
+       at91_add_device_i2c(NULL, 0);
+       /* SPI */
+       at91_add_device_spi(portuxg20_spi_devices, ARRAY_SIZE(portuxg20_spi_devices));
        /* LEDs */
        at91_gpio_leds(portuxg20_leds, ARRAY_SIZE(portuxg20_leds));
 }
 
-static void __init stamp9g20_board_init(void)
+static void __init stamp9g20evb_board_init(void)
 {
-       generic_board_init();
+       stamp9g20_board_init();
+       /* USB Host */
+       at91_add_device_usbh(&usbh_data);
        /* USB Device */
-       at91_add_device_udc(&stamp9g20_udc_data);
+       at91_add_device_udc(&stamp9g20evb_udc_data);
+       /* Ethernet */
+       at91_add_device_eth(&macb_data);
+       /* I2C */
+       at91_add_device_i2c(NULL, 0);
        /* LEDs */
-       at91_gpio_leds(stamp9g20_leds, ARRAY_SIZE(stamp9g20_leds));
+       at91_gpio_leds(stamp9g20evb_leds, ARRAY_SIZE(stamp9g20evb_leds));
 }
 
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
@@ -305,7 +309,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
        .boot_params    = AT91_SDRAM_BASE + 0x100,
        .timer          = &at91sam926x_timer,
-       .map_io         = stamp9g20_map_io,
+       .map_io         = stamp9g20evb_map_io,
        .init_irq       = init_irq,
-       .init_machine   = stamp9g20_board_init,
+       .init_machine   = stamp9g20evb_board_init,
 MACHINE_END
index 7525cee3983f7252fac0542be5955a490ca6869b..9113da6845f17482437ed984bd978b9b28378dfe 100644 (file)
@@ -658,7 +658,7 @@ static void __init at91_upll_usbfs_clock_init(unsigned long main_clock)
        /* Now set uhpck values */
        uhpck.parent = &utmi_clk;
        uhpck.pmc_mask = AT91SAM926x_PMC_UHP;
-       uhpck.rate_hz = utmi_clk.parent->rate_hz;
+       uhpck.rate_hz = utmi_clk.rate_hz;
        uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8);
 }
 
index 57f8ee154943d91b50882a7b01ab2d602d5ba631..27ac6f550fe36eb686e8c180a727c8bf29d2c286 100644 (file)
@@ -74,6 +74,8 @@
 #define                        AT91_MCI_TRTYP_BLOCK    (0 << 19)
 #define                        AT91_MCI_TRTYP_MULTIPLE (1 << 19)
 #define                        AT91_MCI_TRTYP_STREAM   (2 << 19)
+#define                        AT91_MCI_TRTYP_SDIO_BYTE        (4 << 19)
+#define                        AT91_MCI_TRTYP_SDIO_BLOCK       (5 << 19)
 
 #define AT91_MCI_BLKR          0x18            /* Block Register */
 #define                AT91_MCI_BLKR_BCNT(n)   ((0xffff & (n)) << 0)   /* Block count */
diff --git a/arch/arm/mach-at91/include/mach/stamp9g20.h b/arch/arm/mach-at91/include/mach/stamp9g20.h
new file mode 100644 (file)
index 0000000..6120f9c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __MACH_STAMP9G20_H
+#define __MACH_STAMP9G20_H
+
+void stamp9g20_map_io(void);
+void stamp9g20_board_init(void);
+
+#endif
index 14bafc38f2dcc05e51443db5f90f7d1e0d356f4b..ad237a42d265ec6033c85d7684f16940551c17ad 100644 (file)
 #include <linux/string.h>
 #include <linux/clk.h>
 #include <linux/spinlock.h>
+#include <linux/clkdev.h>
 #include <mach/csp/hw_cfg.h>
 #include <mach/csp/chipcHw_def.h>
 #include <mach/csp/chipcHw_reg.h>
 #include <mach/csp/chipcHw_inline.h>
 
-#include <asm/clkdev.h>
-
 #include "clock.h"
 
 #define clk_is_primary(x)       ((x)->type & CLK_TYPE_PRIMARY)
index d3f959e92b2dd2ef15e129a3bd79e52801811efe..8fc2035759fb4fe16d340ecad2f8aec2a83cd300 100644 (file)
 #include <linux/amba/bus.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/clkdev.h>
 
 #include <mach/csp/mm_addr.h>
 #include <mach/hardware.h>
-#include <asm/clkdev.h>
 #include <linux/io.h>
 #include <asm/irq.h>
 #include <asm/hardware/arm_timer.h>
@@ -294,7 +294,6 @@ static struct clocksource clocksource_bcmring_timer1 = {
        .rating = 200,
        .read = bcmring_get_cycles_timer1,
        .mask = CLOCKSOURCE_MASK(32),
-       .shift = 20,
        .flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -303,7 +302,6 @@ static struct clocksource clocksource_bcmring_timer3 = {
        .rating = 100,
        .read = bcmring_get_cycles_timer3,
        .mask = CLOCKSOURCE_MASK(32),
-       .shift = 20,
        .flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -316,10 +314,8 @@ static int __init bcmring_clocksource_init(void)
        writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
               TIMER1_VA_BASE + TIMER_CTRL);
 
-       clocksource_bcmring_timer1.mult =
-           clocksource_khz2mult(TIMER1_FREQUENCY_MHZ * 1000,
-                                clocksource_bcmring_timer1.shift);
-       clocksource_register(&clocksource_bcmring_timer1);
+       clocksource_register_khz(&clocksource_bcmring_timer1,
+                                TIMER1_FREQUENCY_MHZ * 1000);
 
        /* setup timer3 as free-running clocksource */
        writel(0, TIMER3_VA_BASE + TIMER_CTRL);
@@ -328,10 +324,8 @@ static int __init bcmring_clocksource_init(void)
        writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
               TIMER3_VA_BASE + TIMER_CTRL);
 
-       clocksource_bcmring_timer3.mult =
-           clocksource_khz2mult(TIMER3_FREQUENCY_KHZ,
-                                clocksource_bcmring_timer3.shift);
-       clocksource_register(&clocksource_bcmring_timer3);
+       clocksource_register_khz(&clocksource_bcmring_timer3,
+                                TIMER3_FREQUENCY_KHZ);
 
        return 0;
 }
index 9ebfcc46feb1a0f115970cfd53805cc117de57f5..29b13f249aa9b473d11168f42447da800d2dcdb7 100644 (file)
@@ -3,6 +3,7 @@ menu "CNS3XXX platform type"
 
 config MACH_CNS3420VB
        bool "Support for CNS3420 Validation Board"
+       select MIGHT_HAVE_PCI
        help
          Include support for the Cavium Networks CNS3420 MPCore Platform
          Baseboard.
index 9ca4d581016f8e21c307147713a91818fb449c2c..da30078a80c16078192373b67ac0ed59de30a7a7 100644 (file)
@@ -69,13 +69,10 @@ void __init cns3xxx_map_io(void)
 }
 
 /* used by entry-macro.S */
-void __iomem *gic_cpu_base_addr;
-
 void __init cns3xxx_init_irq(void)
 {
-       gic_cpu_base_addr = __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT);
-       gic_dist_init(0, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT), 29);
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_init(0, 29, __io(CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT),
+                __io(CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT));
 }
 
 void cns3xxx_power_off(void)
index 73898a7835d399abddfe4dad39d4f13eeb9e05d0..ffeb3a8b73bacfb1498d6cfa52ae3e1dd8d11439 100644 (file)
@@ -11,7 +11,6 @@
 #ifndef __CNS3XXX_CORE_H
 #define __CNS3XXX_CORE_H
 
-extern void __iomem *gic_cpu_base_addr;
 extern struct sys_timer cns3xxx_timer;
 
 void __init cns3xxx_map_io(void);
index 5e1c5545680f8a46c34723e78f3ba146a1477177..6bd83ed90afe33523c047b7bb22f8cf63c4b94a0 100644 (file)
@@ -9,74 +9,10 @@
  */
 
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
                .macro  disable_fiq
                .endm
 
-               .macro  get_irqnr_preamble, base, tmp
-               ldr     \base, =gic_cpu_base_addr
-               ldr     \base, [\base]
-               .endm
-
                .macro  arch_ret_to_user, tmp1, tmp2
                .endm
-
-               /*
-                * The interrupt numbering scheme is defined in the
-                * interrupt controller spec.  To wit:
-                *
-                * Interrupts 0-15 are IPI
-                * 16-28 are reserved
-                * 29-31 are local.  We allow 30 to be used for the watchdog.
-                * 32-1020 are global
-                * 1021-1022 are reserved
-                * 1023 is "spurious" (no interrupt)
-                *
-                * For now, we ignore all local interrupts so only return an interrupt if it's
-                * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-                *
-                * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-                * valid range for an IRQ (30-1020 inclusive).
-                */
-
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-               ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-               ldr     \tmp, =1021
-
-               bic     \irqnr, \irqstat, #0x1c00
-
-               cmp     \irqnr, #29
-               cmpcc   \irqnr, \irqnr
-               cmpne   \irqnr, \tmp
-               cmpcs   \irqnr, \irqnr
-
-               .endm
-
-               /* We assume that irqstat (the raw value of the IRQ acknowledge
-                * register) is preserved from the macro above.
-                * If there is an IPI, we immediately signal end of interrupt on the
-                * controller, since this requires the original irqstat value which
-                * we won't easily be able to recreate later.
-                */
-
-               .macro test_for_ipi, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               cmp     \irqnr, #16
-               strcc   \irqstat, [\base, #GIC_CPU_EOI]
-               cmpcs   \irqnr, \irqnr
-               .endm
-
-               /* As above, this assumes that irqstat and base are preserved.. */
-
-               .macro test_for_ltirq, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               mov     \tmp, #0
-               cmp     \irqnr, #29
-               moveq   \tmp, #1
-               streq   \irqstat, [\base, #GIC_CPU_EOI]
-               cmp     \tmp, #0
-               .endm
index 11099980b58bdfc2342ba67a8ccd373f07fb4fdf..0dd22031ec6222467a4a3a5ccb0eb27405e1d510 100644 (file)
@@ -68,7 +68,7 @@
 #ifndef __ASSEMBLER__
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #define PLLSTAT_GOSTAT BIT(0)
 #define PLLCMD_GOSET   BIT(0)
index 62b0a90309adff1a817b2953c4b689b39f7b58ba..d1b954955c1242321dc296056d70d4d849db5555 100644 (file)
@@ -22,8 +22,8 @@
 #define __mem_isa(a)           (a)
 
 #ifndef __ASSEMBLER__
-#define __arch_ioremap(p, s, t)        davinci_ioremap(p, s, t)
-#define __arch_iounmap(v)      davinci_iounmap(v)
+#define __arch_ioremap         davinci_ioremap
+#define __arch_iounmap         davinci_iounmap
 
 void __iomem *davinci_ioremap(unsigned long phys, size_t size,
                              unsigned int type);
index 5d1eea026635cb18d3f7e7d595c1b182de21eb20..e1969ce904dc5b4de9ff8f0d44442175c7c2497f 100644 (file)
@@ -286,7 +286,6 @@ static struct clocksource clocksource_davinci = {
        .rating         = 300,
        .read           = read_dummy,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 24,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -400,10 +399,8 @@ static void __init davinci_timer_init(void)
        /* setup clocksource */
        clocksource_davinci.read = read_cycles;
        clocksource_davinci.name = id_to_name[clocksource_id];
-       clocksource_davinci.mult =
-               clocksource_khz2mult(davinci_clock_tick_rate/1000,
-                                    clocksource_davinci.shift);
-       if (clocksource_register(&clocksource_davinci))
+       if (clocksource_register_hz(&clocksource_davinci,
+                                   davinci_clock_tick_rate))
                printk(err, clocksource_davinci.name);
 
        /* setup clockevent */
index ef06c66a6f1630cbab1ec79487382dc8704f4049..ca4de71050973184945297febfc7b2111103f76c 100644 (file)
 #include <linux/string.h>
 #include <linux/io.h>
 #include <linux/spinlock.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 
index daca30b2d5b1ad5d77c03e8166910a8b7ca5a066..3938a563b2807d70f89d4eedcb4e2a2d9537a170 100644 (file)
@@ -22,8 +22,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
index c63a4f5ffcb6e550cb0b88b680d3d42798839e1d..bf30a8c7ce6fdddb1c66d4733dce25a8ca04ae27 100644 (file)
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #define IO_ADDR_CCM(off)       (MX21_IO_ADDRESS(MX21_CCM_BASE_ADDR + (off)))
index 21ef34c501e5d7b870a6a17510a9f43557c9232c..daa0165b6772ffb691ee91a82c21474ca2170203 100644 (file)
@@ -21,8 +21,7 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
index f32f3b8e8ba4f973571f178407de28981488b28b..583f2515c1d58fdfabfb4f122cfbf069769adb5b 100644 (file)
@@ -21,8 +21,8 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #include <mach/clock.h>
index 27db275b367cf167e3dcf018f9d76eb30098b65b..769b0f10c83496a48565ba50b236f9a10aaf9df9 100644 (file)
@@ -4,6 +4,7 @@ menu "Integrator Options"
 
 config ARCH_INTEGRATOR_AP
        bool "Support Integrator/AP and Integrator/PP2 platforms"
+       select MIGHT_HAVE_PCI
        help
          Include support for the ARM(R) Integrator/AP and
          Integrator/PP2 platforms.
index 8f4fb6d638f7ea66717a5afb5d962ef0d88723a3..b8e884b450da7454e77b9fe3d030f2729aacd8aa 100644 (file)
@@ -21,9 +21,8 @@
 #include <linux/amba/bus.h>
 #include <linux/amba/serial.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/irq.h>
index fd684bf205e5d228b11ccf13685d9ed14229be96..5db574f8ae3fd218d393898512930adf53fe2bf3 100644 (file)
@@ -22,9 +22,8 @@
 #include <linux/amba/clcd.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <asm/hardware/icst.h>
 #include <mach/lm.h>
 #include <mach/impd1.h>
index 548208f11179c0aafbed4b3d23b5fc998196f1d3..2774df8021dc65f687f0894271789f8259ef70bc 100644 (file)
@@ -372,7 +372,6 @@ static struct clocksource clocksource_timersp = {
        .rating         = 200,
        .read           = timersp_read,
        .mask           = CLOCKSOURCE_MASK(16),
-       .shift          = 16,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -390,8 +389,7 @@ static void integrator_clocksource_init(u32 khz)
        writel(ctrl, base + TIMER_CTRL);
        writel(0xffff, base + TIMER_LOAD);
 
-       cs->mult = clocksource_khz2mult(khz, cs->shift);
-       clocksource_register(cs);
+       clocksource_register_khz(cs, khz);
 }
 
 static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
index 6258c90d020c30edf75faa7f06976d6cedef2e7e..85e48a5f77b9b2b2e336b72174a022f49dbdfb3c 100644 (file)
@@ -21,9 +21,8 @@
 #include <linux/amba/mmci.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
 #include <asm/irq.h>
@@ -41,7 +40,7 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include "common.h"
 
index a6e0f9e6ddcf4136147eb7dbd78bdab7dfa9b489..dffb234bb967ec9b3e76384a8c9af699747dea12 100644 (file)
@@ -35,7 +35,7 @@ extern u32 iop13xx_atux_mem_base;
 extern size_t iop13xx_atue_mem_size;
 extern size_t iop13xx_atux_mem_size;
 
-#define __arch_ioremap(a, s, f) __iop13xx_ioremap(a, s, f)
-#define __arch_iounmap(a)       __iop13xx_iounmap(a)
+#define __arch_ioremap __iop13xx_ioremap
+#define __arch_iounmap __iop13xx_iounmap
 
 #endif
index 7415e4338651e7c84e2e3a587092a1c1859cda1d..3ad455318868db02adf4c44bd62555f33682af7f 100644 (file)
@@ -58,13 +58,13 @@ static inline unsigned long __lbus_to_virt(dma_addr_t x)
                __dma;                                                  \
        })
 
-#define __arch_page_to_dma(dev, page)                                  \
+#define __arch_pfn_to_dma(dev, pfn)                                    \
        ({                                                              \
                /* __is_lbus_virt() can never be true for RAM pages */  \
-               (dma_addr_t)page_to_phys(page);                         \
+               (dma_addr_t)__pfn_to_phys(pfn);                         \
        })
 
-#define __arch_dma_to_page(dev, addr)  phys_to_page(addr)
+#define __arch_dma_to_pfn(dev, addr)   __phys_to_pfn(addr)
 
 #endif /* CONFIG_ARCH_IOP13XX */
 #endif /* !ASSEMBLY */
index 339e5854728b5f1f3d1434d8570567b3bc6b2fc8..059c783ce0b2c8651ed5864b8fe4a047894e67d9 100644 (file)
@@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr);
 #define __io(p)                ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)           (a)
 
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a)       __iop3xx_iounmap(a)
+#define __arch_ioremap __iop3xx_ioremap
+#define __arch_iounmap __iop3xx_iounmap
 
 #endif
index e99a7ed6d0502e0390ccb9f0e4de0c2f7890ba2c..39e893e97c212ba8b67875ee56fcb708189e4460 100644 (file)
@@ -21,7 +21,7 @@ extern void __iop3xx_iounmap(void __iomem *addr);
 #define __io(p)                ((void __iomem *)IOP3XX_PCI_IO_PHYS_TO_VIRT(p))
 #define __mem_pci(a)           (a)
 
-#define __arch_ioremap(a, s, f) __iop3xx_ioremap(a, s, f)
-#define __arch_iounmap(a)       __iop3xx_iounmap(a)
+#define __arch_ioremap __iop3xx_ioremap
+#define __arch_iounmap __iop3xx_iounmap
 
 #endif
index fd9ef8e519f7dee6c3ea9cbfd7b4e2bca9d96f37..a1749d0fd8961df2d2f57068950660146b325302 100644 (file)
@@ -45,8 +45,8 @@ ixp23xx_iounmap(void __iomem *addr)
        __iounmap(addr);
 }
 
-#define __arch_ioremap(a,s,f)  ixp23xx_ioremap(a,s,f)
-#define __arch_iounmap(a)      ixp23xx_iounmap(a)
+#define __arch_ioremap ixp23xx_ioremap
+#define __arch_iounmap ixp23xx_iounmap
 
 
 #endif
index 24498a932ba65b8054de5ba8229ef0e0c838dd71..a54b3db8036678c8c385705b7c22b763769bb515 100644 (file)
@@ -513,4 +513,4 @@ int dma_set_coherent_mask(struct device *dev, u64 mask)
 
 EXPORT_SYMBOL(ixp4xx_pci_read);
 EXPORT_SYMBOL(ixp4xx_pci_write);
-
+EXPORT_SYMBOL(dma_set_coherent_mask);
index 0bce09799d1841cd6c2ad5ea776b6710091d6a9e..4dbfcbb9163c1252e139edcf0cbb404fc6f0e1ee 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/pgtable.h>
 #include <asm/page.h>
 #include <asm/irq.h>
+#include <asm/sched_clock.h>
 
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -398,6 +399,23 @@ void __init ixp4xx_sys_init(void)
                        ixp4xx_exp_bus_size >> 20);
 }
 
+/*
+ * sched_clock()
+ */
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+       u32 cyc = *IXP4XX_OSTS;
+       return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace ixp4xx_update_sched_clock(void)
+{
+       u32 cyc = *IXP4XX_OSTS;
+       update_sched_clock(&cd, cyc, (u32)~0);
+}
+
 /*
  * clocksource
  */
@@ -411,7 +429,6 @@ static struct clocksource clocksource_ixp4xx = {
        .rating         = 200,
        .read           = ixp4xx_get_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -419,21 +436,9 @@ unsigned long ixp4xx_timer_freq = FREQ;
 EXPORT_SYMBOL(ixp4xx_timer_freq);
 static void __init ixp4xx_clocksource_init(void)
 {
-       clocksource_ixp4xx.mult =
-               clocksource_hz2mult(ixp4xx_timer_freq,
-                                   clocksource_ixp4xx.shift);
-       clocksource_register(&clocksource_ixp4xx);
-}
-
-/*
- * sched_clock()
- */
-unsigned long long sched_clock(void)
-{
-       cycle_t cyc = ixp4xx_get_cycles(NULL);
-       struct clocksource *cs = &clocksource_ixp4xx;
+       init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq);
 
-       return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
+       clocksource_register_hz(&clocksource_ixp4xx, ixp4xx_timer_freq);
 }
 
 /*
index de274a1f19d76a95d715b0d3b05d44469171d3a2..57b5410c31f40dc9db120b0b8f04b0e55c0912d6 100644 (file)
@@ -74,8 +74,8 @@ static inline void __indirect_iounmap(void __iomem *addr)
                __iounmap(addr);
 }
 
-#define __arch_ioremap(a, s, f)                __indirect_ioremap(a, s, f)
-#define __arch_iounmap(a)              __indirect_iounmap(a)
+#define __arch_ioremap                 __indirect_ioremap
+#define __arch_iounmap                 __indirect_iounmap
 
 #define writeb(v, p)                   __indirect_writeb(v, p)
 #define writew(v, p)                   __indirect_writew(v, p)
index 44e8be04f25929b6ef792ac75af0b540a09841d5..1aaddc364f2e6259eca95e6bd4e815322fb67673 100644 (file)
@@ -42,8 +42,8 @@ __arch_iounmap(void __iomem *addr)
                __iounmap(addr);
 }
 
-#define __arch_ioremap(p, s, m)        __arch_ioremap(p, s, m)
-#define __arch_iounmap(a)      __arch_iounmap(a)
+#define __arch_ioremap         __arch_ioremap
+#define __arch_iounmap         __arch_iounmap
 #define __io(a)                        __io(a)
 #define __mem_pci(a)           (a)
 
index fe0c82e30b2dbdc9fb3ff81a1c64c277b7e8843f..f5c39a8c2b00f39b683819e2b0c93ab89705b243 100644 (file)
@@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations"
 
 config MACH_KS8695
        bool "KS8695 development board"
+       select MIGHT_HAVE_PCI
        help
          Say 'Y' here if you want your kernel to run on the original
          Kendin-Micrel KS8695 development board.
index ffa19aae6e054676f039b4691b946966205597b7..bace9a681adcbe5ace6f063f519a384ccf048eae 100644 (file)
@@ -35,17 +35,17 @@ extern struct bus_type platform_bus_type;
                                        __phys_to_virt(x) : __bus_to_virt(x)); })
 #define __arch_virt_to_dma(dev, x)     ({ is_lbus_device(dev) ? \
                                        (dma_addr_t)__virt_to_phys(x) : (dma_addr_t)__virt_to_bus(x); })
-#define __arch_page_to_dma(dev, x)     \
-       ({ dma_addr_t __dma = page_to_phys(page); \
+#define __arch_pfn_to_dma(dev, pfn)    \
+       ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
           if (!is_lbus_device(dev)) \
                __dma = __dma - PHYS_OFFSET + KS8695_PCIMEM_PA; \
           __dma; })
 
-#define __arch_dma_to_page(dev, x)     \
+#define __arch_dma_to_pfn(dev, x)      \
        ({ dma_addr_t __dma = x;                                \
           if (!is_lbus_device(dev))                            \
                __dma += PHYS_OFFSET - KS8695_PCIMEM_PA;        \
-          phys_to_page(__dma);                                 \
+          __phys_to_pfn(__dma);                                \
        })
 
 #endif
index 32d63796430aa12d91e7391fdc7f293bfca92f0d..da0e6498110a4f6400274b74015e964ab81566f5 100644 (file)
 #include <linux/clk.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
 #include <mach/platform.h>
 #include "clock.h"
 #include "common.h"
index 630dd4a74b26d34e637c75ce18bc9df0e6158840..6162ac308c20f7bb1f2c6f6e2d5dcc636ab3ec9c 100644 (file)
@@ -38,7 +38,6 @@ static cycle_t lpc32xx_clksrc_read(struct clocksource *cs)
 
 static struct clocksource lpc32xx_clksrc = {
        .name   = "lpc32xx_clksrc",
-       .shift  = 24,
        .rating = 300,
        .read   = lpc32xx_clksrc_read,
        .mask   = CLOCKSOURCE_MASK(32),
@@ -171,9 +170,7 @@ static void __init lpc32xx_timer_init(void)
        __raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
        __raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
                LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
-       lpc32xx_clksrc.mult = clocksource_hz2mult(clkrate,
-               lpc32xx_clksrc.shift);
-       clocksource_register(&lpc32xx_clksrc);
+       clocksource_register_hz(&lpc32xx_clksrc, clkrate);
 }
 
 struct sys_timer lpc32xx_timer = {
index 016ae94691c04cd42838c9b0af352b68a6e7cacc..9b027d7491f5e9ba854e496568eaa2fafdc9be5e 100644 (file)
@@ -6,7 +6,7 @@
  *  published by the Free Software Foundation.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 struct clkops {
        void                    (*enable)(struct clk *);
index 66528193f9390c623875670a8450486ff637a875..aeb9ae23e6cef69acca858f229920027c13ef7cc 100644 (file)
@@ -26,8 +26,8 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/sched.h>
-#include <linux/cnt32_to_63.h>
 
+#include <asm/sched_clock.h>
 #include <mach/addr-map.h>
 #include <mach/regs-timers.h>
 #include <mach/regs-apbc.h>
 #define MAX_DELTA              (0xfffffffe)
 #define MIN_DELTA              (16)
 
-#define TCR2NS_SCALE_FACTOR    10
-
-static unsigned long tcr2ns_scale;
-
-static void __init set_tcr2ns_scale(unsigned long tcr_rate)
-{
-       unsigned long long v = 1000000000ULL << TCR2NS_SCALE_FACTOR;
-       do_div(v, tcr_rate);
-       tcr2ns_scale = v;
-       /*
-        * We want an even value to automatically clear the top bit
-        * returned by cnt32_to_63() without an additional run time
-        * instruction. So if the LSB is 1 then round it up.
-        */
-       if (tcr2ns_scale & 1)
-               tcr2ns_scale++;
-}
+static DEFINE_CLOCK_DATA(cd);
 
 /*
  * FIXME: the timer needs some delay to stablize the counter capture
@@ -75,10 +59,16 @@ static inline uint32_t timer_read(void)
        return __raw_readl(TIMERS_VIRT_BASE + TMR_CVWR(0));
 }
 
-unsigned long long sched_clock(void)
+unsigned long long notrace sched_clock(void)
 {
-       unsigned long long v = cnt32_to_63(timer_read());
-       return (v * tcr2ns_scale) >> TCR2NS_SCALE_FACTOR;
+       u32 cyc = timer_read();
+       return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace mmp_update_sched_clock(void)
+{
+       u32 cyc = timer_read();
+       update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
@@ -146,7 +136,6 @@ static cycle_t clksrc_read(struct clocksource *cs)
 
 static struct clocksource cksrc = {
        .name           = "clocksource",
-       .shift          = 20,
        .rating         = 200,
        .read           = clksrc_read,
        .mask           = CLOCKSOURCE_MASK(32),
@@ -186,17 +175,15 @@ void __init timer_init(int irq)
 {
        timer_config();
 
-       set_tcr2ns_scale(CLOCK_TICK_RATE);
+       init_sched_clock(&cd, mmp_update_sched_clock, 32, CLOCK_TICK_RATE);
 
        ckevt.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, ckevt.shift);
        ckevt.max_delta_ns = clockevent_delta2ns(MAX_DELTA, &ckevt);
        ckevt.min_delta_ns = clockevent_delta2ns(MIN_DELTA, &ckevt);
        ckevt.cpumask = cpumask_of(0);
 
-       cksrc.mult = clocksource_hz2mult(CLOCK_TICK_RATE, cksrc.shift);
-
        setup_irq(irq, &timer_irq);
 
-       clocksource_register(&cksrc);
+       clocksource_register_hz(&cksrc, CLOCK_TICK_RATE);
        clockevents_register_device(&ckevt);
 }
index 7486a681cc7192bfd5c7b04fca59757ca256f7ac..9b5eb2b4ae1b8507a78927e43ce8c9c27b4220f6 100644 (file)
@@ -28,8 +28,6 @@
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
-void __iomem *gic_cpu_base_addr;
-
 unsigned long clk_get_max_axi_khz(void)
 {
        return 0;
@@ -44,9 +42,8 @@ static void __init msm8x60_init_irq(void)
 {
        unsigned int i;
 
-       gic_dist_init(0, MSM_QGIC_DIST_BASE, GIC_PPI_START);
-       gic_cpu_base_addr = (void *)MSM_QGIC_CPU_BASE;
-       gic_cpu_init(0, MSM_QGIC_CPU_BASE);
+       gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+                (void *)MSM_QGIC_CPU_BASE);
 
        /* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
        writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
index 3ff7bf5e679ec7b00efbd08a3a44af8d4cbebfc6..a95f7b9efe31b3d8e2e95a2d76c561df69d2e657 100644 (file)
@@ -31,9 +31,9 @@
 
 #include <asm/hardware/gic.h>
 
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 950100f19d0786a866927a2374ab5d4d6156db85..595be7fea31a64a974773b5f61e0687cdd4a468b 100644 (file)
@@ -137,7 +137,6 @@ static struct msm_clock msm_clocks[] = {
                        .rating         = 200,
                        .read           = msm_gpt_read,
                        .mask           = CLOCKSOURCE_MASK(32),
-                       .shift          = 17,
                        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
                },
                .irq = {
@@ -164,7 +163,6 @@ static struct msm_clock msm_clocks[] = {
                        .rating         = 300,
                        .read           = msm_dgt_read,
                        .mask           = CLOCKSOURCE_MASK((32 - MSM_DGT_SHIFT)),
-                       .shift          = 24 - MSM_DGT_SHIFT,
                        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
                },
                .irq = {
@@ -205,8 +203,7 @@ static void __init msm_timer_init(void)
                ce->min_delta_ns = clockevent_delta2ns(4, ce);
                ce->cpumask = cpumask_of(0);
 
-               cs->mult = clocksource_hz2mult(clock->freq, cs->shift);
-               res = clocksource_register(cs);
+               res = clocksource_register_hz(cs, clock->freq);
                if (res)
                        printk(KERN_ERR "msm_timer_init: clocksource_register "
                               "failed for %s\n", cs->name);
index 4193cf5a2637ea23d6e7ee030adc5f83a760170e..d423cac8cab76c6bffe0957234c075dbf83765b5 100644 (file)
@@ -23,8 +23,8 @@
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #include <mach/clock.h>
index 22259d95583753e60f44ed3405450ade0bbf242f..448a038cd1ec15a5420f0ba5b0596c3a1d79dd84 100644 (file)
@@ -21,8 +21,7 @@
 #include <linux/list.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
index b21bc47d4827e769a22eed0df4624a5e47aa1bdd..785e1a33618355098e9b9202b4dfe78deb3afcff 100644 (file)
@@ -14,8 +14,8 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/div64.h>
 
 #include <mach/hardware.h>
index 5c85075d8a56b9b6c40059785dd9a4cd69658632..9fab505f1eb1a2c73b14ea489553442956782af0 100644 (file)
@@ -2,12 +2,12 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
 
-#include <asm/clkdev.h>
 #include <asm/bug.h>
 #include <asm/div64.h>
 
index 82801dbf0579a024cb7a5df294db3105eaf1a464..f12f22d09b6c7ba157b6aa8de79918cdde76e74e 100644 (file)
@@ -114,7 +114,6 @@ static struct clocksource clocksource_netx = {
        .rating         = 200,
        .read           = netx_get_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -151,9 +150,7 @@ static void __init netx_timer_init(void)
        writel(NETX_GPIO_COUNTER_CTRL_RUN,
                        NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
 
-       clocksource_netx.mult =
-               clocksource_hz2mult(CLOCK_TICK_RATE, clocksource_netx.shift);
-       clocksource_register(&clocksource_netx);
+       clocksource_register_hz(&clocksource_netx, CLOCK_TICK_RATE);
 
        netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
                        netx_clockevent.shift);
index 89f793adf77643093c9e465c35447553102ae295..48a59f24e10c16bd6aed13b846f86973e2a9324a 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include "clock.h"
 
 /*
index 77281260358a504f3f5be293074636b8502deed8..9ca32f55728bda7e8d74ee01883ccfcf2cdb05f7 100644 (file)
@@ -35,7 +35,6 @@ static struct clocksource ns9360_clocksource = {
        .rating = 300,
        .read   = ns9360_clocksource_read,
        .mask   = CLOCKSOURCE_MASK(32),
-       .shift  = 20,
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -148,10 +147,7 @@ static void __init ns9360_timer_init(void)
 
        __raw_writel(tc, SYS_TC(TIMER_CLOCKSOURCE));
 
-       ns9360_clocksource.mult = clocksource_hz2mult(ns9360_cpuclock(),
-                       ns9360_clocksource.shift);
-
-       clocksource_register(&ns9360_clocksource);
+       clocksource_register_hz(&ns9360_clocksource, ns9360_cpuclock());
 
        latch = SH_DIV(ns9360_cpuclock(), HZ, 0);
 
index 18e51be4816f7bece014b71f8ac16f380ab416f1..4de1f1da9dc52d43c2898cbfa1d1d5a38efc382f 100644 (file)
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 2 of the License.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 void nuc93x_clk_enable(struct clk *clk, int enable);
 void clks_register(struct clk_lookup *clks, size_t num);
index b8c7fb9d792108adbccb8b342083c7551830924f..84ef70476b511e1005b75f7e80b633ef3a66c7fd 100644 (file)
@@ -17,9 +17,9 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
-#include <asm/clkdev.h>
 
 #include <plat/cpu.h>
 #include <plat/usb.h>
index 1be6a214d88de2d5cbc77dd259c84a42f7548f06..abb34ff2041bba2d4cb0e3a61a26c33adaffcea9 100644 (file)
@@ -208,7 +208,6 @@ static struct clocksource clocksource_mpu = {
        .rating         = 300,
        .read           = mpu_read,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 24,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -217,13 +216,10 @@ static void __init omap_init_clocksource(unsigned long rate)
        static char err[] __initdata = KERN_ERR
                        "%s: can't register clocksource!\n";
 
-       clocksource_mpu.mult
-               = clocksource_khz2mult(rate/1000, clocksource_mpu.shift);
-
        setup_irq(INT_TIMER2, &omap_mpu_timer2_irq);
        omap_mpu_timer_start(1, ~0, 1);
 
-       if (clocksource_register(&clocksource_mpu))
+       if (clocksource_register_hz(&clocksource_mpu, rate))
                printk(err, clocksource_mpu.name);
 }
 
index ed8d330522f18043a0b8ce6be06023a92988e988..ebb888f59365c29ffe8567bbaa6321de9358d9b4 100644 (file)
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <linux/clkdev.h>
 
 #include <plat/cpu.h>
 #include <plat/clock.h>
-#include <asm/clkdev.h>
 
 #include "clock.h"
 #include "prm.h"
index 06e64e1fc28a7e18957ff0bb9fe620e7487f7284..d54c4f89a8bd0b912dc9f5da70e31e5305d1e2ce 100644 (file)
@@ -105,6 +105,35 @@ omap_irq_base:     .word   0
 9999:
                .endm
 
+#ifdef CONFIG_SMP
+               /* We assume that irqstat (the raw value of the IRQ acknowledge
+                * register) is preserved from the macro above.
+                * If there is an IPI, we immediately signal end of interrupt
+                * on the controller, since this requires the original irqstat
+                * value which we won't easily be able to recreate later.
+                */
+
+               .macro test_for_ipi, irqnr, irqstat, base, tmp
+               bic     \irqnr, \irqstat, #0x1c00
+               cmp     \irqnr, #16
+               it      cc
+               strcc   \irqstat, [\base, #GIC_CPU_EOI]
+               it      cs
+               cmpcs   \irqnr, \irqnr
+               .endm
+
+               /* As above, this assumes that irqstat and base are preserved */
+
+               .macro test_for_ltirq, irqnr, irqstat, base, tmp
+               bic     \irqnr, \irqstat, #0x1c00
+               mov     \tmp, #0
+               cmp     \irqnr, #29
+               itt     eq
+               moveq   \tmp, #1
+               streq   \irqstat, [\base, #GIC_CPU_EOI]
+               cmp     \tmp, #0
+               .endm
+#endif /* CONFIG_SMP */
 
 #else  /* MULTI_OMAP2 */
 
@@ -141,74 +170,16 @@ omap_irq_base:    .word   0
 
 
 #ifdef CONFIG_ARCH_OMAP4
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
                .macro  get_irqnr_preamble, base, tmp
                ldr     \base, =OMAP4_IRQ_BASE
                .endm
 
-               /*
-                * The interrupt numbering scheme is defined in the
-                * interrupt controller spec.  To wit:
-                *
-                * Interrupts 0-15 are IPI
-                * 16-28 are reserved
-                * 29-31 are local.  We allow 30 to be used for the watchdog.
-                * 32-1020 are global
-                * 1021-1022 are reserved
-                * 1023 is "spurious" (no interrupt)
-                *
-                * For now, we ignore all local interrupts so only return an
-                * interrupt if it's between 30 and 1020.  The test_for_ipi
-                * routine below will pick up on IPIs.
-                * A simple read from the controller will tell us the number
-                * of the highest priority enabled interrupt.
-                * We then just need to check whether it is in the
-                * valid range for an IRQ (30-1020 inclusive).
-                */
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-               ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-               ldr     \tmp, =1021
-
-               bic     \irqnr, \irqstat, #0x1c00
-
-               cmp     \irqnr, #29
-               cmpcc   \irqnr, \irqnr
-               cmpne   \irqnr, \tmp
-               cmpcs   \irqnr, \irqnr
-               .endm
 #endif
-#endif /* MULTI_OMAP2 */
-
-#ifdef CONFIG_SMP
-               /* We assume that irqstat (the raw value of the IRQ acknowledge
-                * register) is preserved from the macro above.
-                * If there is an IPI, we immediately signal end of interrupt
-                * on the controller, since this requires the original irqstat
-                * value which we won't easily be able to recreate later.
-                */
 
-               .macro test_for_ipi, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               cmp     \irqnr, #16
-               it      cc
-               strcc   \irqstat, [\base, #GIC_CPU_EOI]
-               it      cs
-               cmpcs   \irqnr, \irqnr
-               .endm
-
-               /* As above, this assumes that irqstat and base are preserved */
-
-               .macro test_for_ltirq, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               mov     \tmp, #0
-               cmp     \irqnr, #29
-               itt     eq
-               moveq   \tmp, #1
-               streq   \irqstat, [\base, #GIC_CPU_EOI]
-               cmp     \tmp, #0
-               .endm
-#endif /* CONFIG_SMP */
+#endif /* MULTI_OMAP2 */
 
                .macro  irq_prio_table
                .endm
index 2744dfee1ff4875cad6e6b2faac9a292020e2065..5b0270b289348116fe92a7741f2cab6f6aa0350b 100644 (file)
@@ -24,7 +24,6 @@
 extern void __iomem *l2cache_base;
 #endif
 
-extern void __iomem *gic_cpu_base_addr;
 extern void __iomem *gic_dist_base_addr;
 
 extern void __init gic_init_irq(void);
index 6cee456ca542e078fa9eaf7bcfd03e03f562535b..4976b9393e49123ad04eaa8fabb15b7ca4357c99 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 #include <mach/omap4-common.h>
 
-static DECLARE_COMPLETION(cpu_killed);
-
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -35,15 +32,6 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               pr_crit("platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-       pr_notice("CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
        flush_cache_all();
        dsb();
 
index 9e9f70e18e3c95436cf6b957e2791175a3cdc90a..b66cfe8bc464fad189d41d2e1f8f03ac898a51e6 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
 #include <mach/omap4-common.h>
 /* SCU base address */
 static void __iomem *scu_base;
 
-/*
- * Use SCU config register to count number of cores
- */
-static inline unsigned int get_core_count(void)
-{
-       if (scu_base)
-               return scu_get_core_count(scu_base);
-       return 1;
-}
-
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * If any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_secondary_init(0);
 
        /*
         * Synchronise with the boot thread.
@@ -76,7 +63,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
        omap_modify_auxcoreboot0(0x200, 0xfffffdff);
        flush_cache_all();
        smp_wmb();
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        /*
         * Now the secondary core is starting up let it run its
@@ -118,25 +105,9 @@ void __init smp_init_cpus(void)
        scu_base = ioremap(OMAP44XX_SCU_BASE, SZ_256);
        BUG_ON(!scu_base);
 
-       ncores = get_core_count();
-
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-       unsigned int ncores = get_core_count();
-       unsigned int cpu = smp_processor_id();
-       int i;
+       ncores = scu_get_core_count(scu_base);
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "OMAP4: strange core count of 0? Default to 1\n");
-               ncores = 1;
-       }
-
        if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "OMAP4: no. of cores (%d) greater than configured "
@@ -144,13 +115,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                       ncores, NR_CPUS);
                ncores = NR_CPUS;
        }
-       smp_store_cpu_info(cpu);
 
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+       int i;
 
        /*
         * Initialise the present map, which describes the set of CPUs
@@ -159,18 +131,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-
-               /*
-                * Initialise the SCU and wake up the secondary core using
-                * wakeup_secondary().
-                */
-               scu_enable(scu_base);
-               wakeup_secondary();
-       }
+       /*
+        * Initialise the SCU and wake up the secondary core using
+        * wakeup_secondary().
+        */
+       scu_enable(scu_base);
+       wakeup_secondary();
 }
index 2f895553e6a815e5df735b47fbf89b2c191ba8d8..666e852988d5d21dfcda20e8ea7779a17fe94d97 100644 (file)
 void __iomem *l2cache_base;
 #endif
 
-void __iomem *gic_cpu_base_addr;
 void __iomem *gic_dist_base_addr;
 
 
 void __init gic_init_irq(void)
 {
+       void __iomem *gic_cpu_base;
+
        /* Static mapping, never released */
        gic_dist_base_addr = ioremap(OMAP44XX_GIC_DIST_BASE, SZ_4K);
        BUG_ON(!gic_dist_base_addr);
-       gic_dist_init(0, gic_dist_base_addr, 29);
 
        /* Static mapping, never released */
-       gic_cpu_base_addr = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
-       BUG_ON(!gic_cpu_base_addr);
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_cpu_base = ioremap(OMAP44XX_GIC_CPU_BASE, SZ_512);
+       BUG_ON(!gic_cpu_base);
+
+       gic_init(0, 29, gic_dist_base_addr, gic_cpu_base);
 }
 
 #ifdef CONFIG_CACHE_L2X0
index e13c29eecf2b54d3cdf17cdff24ea18c8f2f7ee9..a7816dbdc6b17ca952739e48c0cd2d06dcf57af6 100644 (file)
@@ -195,7 +195,6 @@ static struct clocksource clocksource_gpt = {
        .rating         = 300,
        .read           = clocksource_read_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 24,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -220,9 +219,7 @@ static void __init omap2_gp_clocksource_init(void)
 
        omap_dm_timer_set_load_start(gpt, 1, 0);
 
-       clocksource_gpt.mult =
-               clocksource_khz2mult(tick_rate/1000, clocksource_gpt.shift);
-       if (clocksource_register(&clocksource_gpt))
+       if (clocksource_register_hz(&clocksource_gpt, tick_rate))
                printk(err2, clocksource_gpt.name);
 }
 #endif
index c47b033bd999e67588e037522aa897aefae6bc12..c5196101a237ac960ccd1eefce8792e6483a8a93 100644 (file)
@@ -38,8 +38,8 @@ __arch_iounmap(void __iomem *addr)
                __iounmap(addr);
 }
 
-#define __arch_ioremap(p, s, m)        __arch_ioremap(p, s, m)
-#define __arch_iounmap(a)      __arch_iounmap(a)
+#define __arch_ioremap         __arch_ioremap
+#define __arch_iounmap         __arch_iounmap
 #define __io(a)                        __typesafe_io(a)
 #define __mem_pci(a)           (a)
 
index 9d1975fa4d9f2c2e71e3782c7716bd66c5c67dff..a4a3819c96cbf2777da665a5ccef10323f7caab5 100644 (file)
@@ -21,8 +21,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/hardware.h>
 #include <mach/clock.h>
index 1df6db6a136e0f90aff94166235bcafe02ddd477..2fc9f94cdd29af9abd575dbf30c92acd379a1a24 100644 (file)
@@ -98,6 +98,7 @@ config MACH_ARMCORE
        select PXA27x
        select IWMMXT
        select PXA25x
+       select MIGHT_HAVE_PCI
 
 config MACH_EM_X270
        bool "CompuLab EM-x270 platform"
@@ -544,6 +545,7 @@ config MACH_ICONTROL
 config ARCH_PXA_ESERIES
        bool "PXA based Toshiba e-series PDAs"
        select PXA25x
+       select FB_W100
 
 config MACH_E330
        bool "Toshiba e330"
index 8184fe2d71c34c55c9d783645424c5073ce66d31..d5152220ce947607f072b47ae01d21419170c3b3 100644 (file)
@@ -6,8 +6,7 @@
 #include <linux/clk.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include "clock.h"
 
index 6e949944f2ec97233dfe0c74e4fd34ff22ad928c..f9f349a21b54ee7f2d2c1b67f5079efc11b5ad65 100644 (file)
@@ -1,5 +1,5 @@
+#include <linux/clkdev.h>
 #include <linux/sysdev.h>
-#include <asm/clkdev.h>
 
 struct clkops {
        void                    (*enable)(struct clk *);
index 2f5b08aeb52e8c0297f79f6015cbbc0e60acca1c..c551da86baf60b1b10bddb6f021a53de3ae82b24 100644 (file)
@@ -353,8 +353,8 @@ resume_turn_on_mmu:
 
        @ Let us ensure we jump to resume_after_mmu only when the mcr above
        @ actually took effect.  They call it the "cpwait" operation.
-       mrc     p15, 0, r1, c2, c0, 0           @ queue a dependency on CP15
-       sub     pc, r2, r1, lsr #32             @ jump to virtual addr
+       mrc     p15, 0, r0, c2, c0, 0           @ queue a dependency on CP15
+       sub     pc, r2, r0, lsr #32             @ jump to virtual addr
        nop
        nop
        nop
index 293e40aeaf29d2b7ce2bc3c8b33477b2a1bef4cc..e7f64d9b4f2d02a084f9208697fc93d84b6b15f8 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
 #include <linux/sched.h>
-#include <linux/cnt32_to_63.h>
 
 #include <asm/div64.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
+#include <asm/sched_clock.h>
 #include <mach/regs-ost.h>
 
 /*
  * long as there is always less than 582 seconds between successive
  * calls to sched_clock() which should always be the case in practice.
  */
+static DEFINE_CLOCK_DATA(cd);
 
-#define OSCR2NS_SCALE_FACTOR 10
-
-static unsigned long oscr2ns_scale;
-
-static void __init set_oscr2ns_scale(unsigned long oscr_rate)
+unsigned long long notrace sched_clock(void)
 {
-       unsigned long long v = 1000000000ULL << OSCR2NS_SCALE_FACTOR;
-       do_div(v, oscr_rate);
-       oscr2ns_scale = v;
-       /*
-        * We want an even value to automatically clear the top bit
-        * returned by cnt32_to_63() without an additional run time
-        * instruction. So if the LSB is 1 then round it up.
-        */
-       if (oscr2ns_scale & 1)
-               oscr2ns_scale++;
+       u32 cyc = OSCR;
+       return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
-unsigned long long sched_clock(void)
+static void notrace pxa_update_sched_clock(void)
 {
-       unsigned long long v = cnt32_to_63(OSCR);
-       return (v * oscr2ns_scale) >> OSCR2NS_SCALE_FACTOR;
+       u32 cyc = OSCR;
+       update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 
@@ -127,7 +116,6 @@ static struct clocksource cksrc_pxa_oscr0 = {
        .rating         = 200,
        .read           = pxa_read_oscr,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -145,7 +133,7 @@ static void __init pxa_timer_init(void)
        OIER = 0;
        OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
 
-       set_oscr2ns_scale(clock_tick_rate);
+       init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate);
 
        ckevt_pxa_osmr0.mult =
                div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
@@ -155,12 +143,9 @@ static void __init pxa_timer_init(void)
                clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_pxa_osmr0) + 1;
        ckevt_pxa_osmr0.cpumask = cpumask_of(0);
 
-       cksrc_pxa_oscr0.mult =
-               clocksource_hz2mult(clock_tick_rate, cksrc_pxa_oscr0.shift);
-
        setup_irq(IRQ_OST0, &pxa_ost0_irq);
 
-       clocksource_register(&cksrc_pxa_oscr0);
+       clocksource_register_hz(&cksrc_pxa_oscr0, clock_tick_rate);
        clockevents_register_device(&ckevt_pxa_osmr0);
 }
 
index 07c08151dfe6434be39b510e215acd79e86ea297..1c6602cf50e4dd53c8f5d8022118aca0d008968e 100644 (file)
@@ -30,8 +30,8 @@
 #include <linux/ata_platform.h>
 #include <linux/amba/mmci.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/system.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
 
 #include <asm/hardware/gic.h>
 
-#include <mach/clkdev.h>
 #include <mach/platform.h>
 #include <mach/irqs.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
-#include "core.h"
+#include <plat/sched_clock.h>
 
-/* used by entry-macro.S and platsmp.c */
-void __iomem *gic_cpu_base_addr;
+#include "core.h"
 
 #ifdef CONFIG_ZONE_DMA
 /*
@@ -657,6 +655,12 @@ void realview_leds_event(led_event_t ledevt)
 }
 #endif /* CONFIG_LEDS */
 
+/*
+ * The sched_clock counter
+ */
+#define REFCOUNTER             (__io_address(REALVIEW_SYS_BASE) + \
+                                REALVIEW_SYS_24MHz_OFFSET)
+
 /*
  * Where is the timer (VA)?
  */
@@ -672,6 +676,8 @@ void __init realview_timer_init(unsigned int timer_irq)
 {
        u32 val;
 
+       versatile_sched_clock_init(REFCOUNTER, 24000000);
+
        /* 
         * set clock frequency: 
         *      REALVIEW_REFCLK is 32KHz
index 781bca68a9fadcbe4dec1883e837dcf33a167866..693239ddc39e4cc15653575c9c50081cf10c9213 100644 (file)
@@ -53,7 +53,6 @@ extern struct platform_device realview_i2c_device;
 extern struct mmci_platform_data realview_mmc0_plat_data;
 extern struct mmci_platform_data realview_mmc1_plat_data;
 extern struct clcd_board clcd_plat_data;
-extern void __iomem *gic_cpu_base_addr;
 extern void __iomem *timer0_va_base;
 extern void __iomem *timer1_va_base;
 extern void __iomem *timer2_va_base;
index f95521a5e5ce6bfb1b32e264fc4d70db501bae7b..a87523d095e63733dd63046295679399f54773d3 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
        unsigned int v;
@@ -34,10 +31,10 @@ static inline void cpu_enter_lowpower(void)
        "       bic     %0, %0, #0x20\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
        "       mrc     p15, 0, %0, c1, c0, 0\n"
-       "       bic     %0, %0, #0x04\n"
+       "       bic     %0, %0, %2\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
          : "=&r" (v)
-         : "r" (0)
+         : "r" (0), "Ir" (CR_C)
          : "cc");
 }
 
@@ -46,17 +43,17 @@ static inline void cpu_leave_lowpower(void)
        unsigned int v;
 
        asm volatile(   "mrc    p15, 0, %0, c1, c0, 0\n"
-       "       orr     %0, %0, #0x04\n"
+       "       orr     %0, %0, %1\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
        "       mrc     p15, 0, %0, c1, c0, 1\n"
        "       orr     %0, %0, #0x20\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
          : "=&r" (v)
-         :
+         : "Ir" (CR_C)
          : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
        /*
         * there is no power-control hardware on this platform, so all
@@ -80,22 +77,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
                }
 
                /*
-                * getting here, means that we have come out of WFI without
+                * Getting here, means that we have come out of WFI without
                 * having been woken up - this shouldn't happen
                 *
-                * The trouble is, letting people know about this is not really
-                * possible, since we are currently running incoherently, and
-                * therefore cannot safely call printk() or anything else
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
                 */
-#ifdef DEBUG
-               printk("CPU%u: spurious wakeup call\n", cpu);
-#endif
+               (*spurious)++;
        }
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -105,30 +99,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-#endif
-
-       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
+       int spurious = 0;
 
        /*
         * we're ready for shutdown now, so do it
         */
        cpu_enter_lowpower();
-       platform_do_lowpower(cpu);
+       platform_do_lowpower(cpu, &spurious);
 
        /*
         * bring this CPU back into the world of cache
         * coherency, and then restore interrupts
         */
        cpu_leave_lowpower();
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
 
 int platform_cpu_disable(unsigned int cpu)
index 340a5c276946b596aef73a9a5b52ad02d7384d6e..4071164aebaaafe9872b0557c599d5788a3b9859 100644 (file)
@@ -8,74 +8,11 @@
  * warranty of any kind, whether express or implied.
  */
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
                .macro  disable_fiq
                .endm
 
-               .macro  get_irqnr_preamble, base, tmp
-               ldr     \base, =gic_cpu_base_addr
-               ldr     \base, [\base]
-               .endm
-
                .macro  arch_ret_to_user, tmp1, tmp2
                .endm
 
-               /*
-                * The interrupt numbering scheme is defined in the
-                * interrupt controller spec.  To wit:
-                *
-                * Interrupts 0-15 are IPI
-                * 16-28 are reserved
-                * 29-31 are local.  We allow 30 to be used for the watchdog.
-                * 32-1020 are global
-                * 1021-1022 are reserved
-                * 1023 is "spurious" (no interrupt)
-                *
-                * For now, we ignore all local interrupts so only return an interrupt if it's
-                * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-                *
-                * A simple read from the controller will tell us the number of the highest
-                 * priority enabled interrupt.  We then just need to check whether it is in the
-                * valid range for an IRQ (30-1020 inclusive).
-                */
-
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-               ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-               ldr     \tmp, =1021
-
-               bic     \irqnr, \irqstat, #0x1c00
-
-               cmp     \irqnr, #29
-               cmpcc   \irqnr, \irqnr
-               cmpne   \irqnr, \tmp
-               cmpcs   \irqnr, \irqnr
-
-               .endm
-
-               /* We assume that irqstat (the raw value of the IRQ acknowledge
-                * register) is preserved from the macro above.
-                * If there is an IPI, we immediately signal end of interrupt on the
-                * controller, since this requires the original irqstat value which
-                * we won't easily be able to recreate later.
-                */
-
-               .macro test_for_ipi, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               cmp     \irqnr, #16
-               strcc   \irqstat, [\base, #GIC_CPU_EOI]
-               cmpcs   \irqnr, \irqnr
-               .endm
-
-               /* As above, this assumes that irqstat and base are preserved.. */
-
-               .macro test_for_ltirq, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               mov     \tmp, #0
-               cmp     \irqnr, #29
-               moveq   \tmp, #1
-               streq   \irqstat, [\base, #GIC_CPU_EOI]
-               cmp     \tmp, #0
-               .endm
index d3cd265cb058c4acf0d29c4a14a16e097aa1ee55..c8221b38ee7c32ec2e53d5a24fe6c0a90e6c3743 100644 (file)
@@ -2,14 +2,13 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 009265818d55752aa401ad8bde837d59a6b89ea5..a22bf67f2f78ca8aada648cc2ba2a6737de9f53f 100644 (file)
@@ -19,7 +19,6 @@
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/localtimer.h>
 #include <asm/unified.h>
 
 #include <mach/board-eb.h>
@@ -37,6 +36,19 @@ extern void realview_secondary_startup(void);
  */
 volatile int __cpuinitdata pen_release = -1;
 
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+       pen_release = val;
+       smp_wmb();
+       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
 static void __iomem *scu_base_addr(void)
 {
        if (machine_is_realview_eb_mp())
@@ -50,33 +62,22 @@ static void __iomem *scu_base_addr(void)
                return (void __iomem *)0;
 }
 
-static inline unsigned int get_core_count(void)
-{
-       void __iomem *scu_base = scu_base_addr();
-       if (scu_base)
-               return scu_get_core_count(scu_base);
-       return 1;
-}
-
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_secondary_init(0);
 
        /*
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
-       pen_release = -1;
-       smp_wmb();
+       write_pen_release(-1);
 
        /*
         * Synchronise with the boot thread.
@@ -103,20 +104,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * Note that "pen_release" is the hardware CPU ID, whereas
         * "cpu" is Linux's internal ID.
         */
-       pen_release = cpu;
-       flush_cache_all();
+       write_pen_release(cpu);
 
        /*
-        * XXX
-        *
-        * This is a later addition to the booting protocol: the
-        * bootMonitor now puts secondary cores into WFI, so
-        * poke_milo() no longer gets the cores moving; we need
-        * to send a soft interrupt to wake the secondary core.
-        * Use smp_cross_call() for this, since there's little
-        * point duplicating the code here
+        * Send the secondary CPU a soft interrupt, thereby causing
+        * the boot monitor to read the system wide flags register,
+        * and branch to the address found there.
         */
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
@@ -136,48 +131,18 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
        return pen_release != -1 ? -ENOSYS : 0;
 }
 
-static void __init poke_milo(void)
-{
-       /* nobody is to be released from the pen yet */
-       pen_release = -1;
-
-       /*
-        * Write the address of secondary startup into the system-wide flags
-        * register. The BootMonitor waits for this register to become
-        * non-zero.
-        */
-       __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
-                    __io_address(REALVIEW_SYS_FLAGSSET));
-
-       mb();
-}
-
 /*
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
  */
 void __init smp_init_cpus(void)
 {
-       unsigned int i, ncores = get_core_count();
+       void __iomem *scu_base = scu_base_addr();
+       unsigned int i, ncores;
 
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-       unsigned int ncores = get_core_count();
-       unsigned int cpu = smp_processor_id();
-       int i;
+       ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "Realview: strange CM count of 0? Default to 1\n");
-
-               ncores = 1;
-       }
-
        if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "Realview: no. of cores (%d) greater than configured "
@@ -186,13 +151,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
                ncores = NR_CPUS;
        }
 
-       smp_store_cpu_info(cpu);
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+}
 
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+       int i;
 
        /*
         * Initialise the present map, which describes the set of CPUs
@@ -201,21 +166,14 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
+       scu_enable(scu_base_addr());
+
        /*
-        * Initialise the SCU if there are more than one CPU and let
-        * them know where to start. Note that, on modern versions of
-        * MILO, the "poke" doesn't actually do anything until each
-        * individual core is sent a soft interrupt to get it out of
-        * WFI
+        * Write the address of secondary startup into the
+        * system-wide flags register. The BootMonitor waits
+        * until it receives a soft interrupt, and then the
+        * secondary CPU branches to this address.
         */
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-
-               scu_enable(scu_base_addr());
-               poke_milo();
-       }
+       __raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
+                    __io_address(REALVIEW_SYS_FLAGSSET));
 }
index f2697106f809fd44a5ad35903496412602dfa1ba..6ef5c5e528b251b86ec91f6f7102788265a62ec3 100644 (file)
@@ -364,21 +364,19 @@ static void __init gic_init_irq(void)
                writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 
                /* core tile GIC, primary */
-               gic_cpu_base_addr = __io_address(REALVIEW_EB11MP_GIC_CPU_BASE);
-               gic_dist_init(0, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE), 29);
-               gic_cpu_init(0, gic_cpu_base_addr);
+               gic_init(0, 29, __io_address(REALVIEW_EB11MP_GIC_DIST_BASE),
+                        __io_address(REALVIEW_EB11MP_GIC_CPU_BASE));
 
 #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
                /* board GIC, secondary */
-               gic_dist_init(1, __io_address(REALVIEW_EB_GIC_DIST_BASE), 64);
-               gic_cpu_init(1, __io_address(REALVIEW_EB_GIC_CPU_BASE));
+               gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+                        __io_address(REALVIEW_EB_GIC_CPU_BASE));
                gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
 #endif
        } else {
                /* board GIC, primary */
-               gic_cpu_base_addr = __io_address(REALVIEW_EB_GIC_CPU_BASE);
-               gic_dist_init(0, __io_address(REALVIEW_EB_GIC_DIST_BASE), 29);
-               gic_cpu_init(0, gic_cpu_base_addr);
+               gic_init(0, 29, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+                        __io_address(REALVIEW_EB_GIC_CPU_BASE));
        }
 }
 
index a4125619d71b2ed54bcaad9431524803c7fe79f1..cbdc97a5685fc11ad764587414f56a8420cb02ab 100644 (file)
@@ -304,13 +304,14 @@ static struct platform_device char_lcd_device = {
 static void __init gic_init_irq(void)
 {
        /* ARM1176 DevChip GIC, primary */
-       gic_cpu_base_addr = __io_address(REALVIEW_DC1176_GIC_CPU_BASE);
-       gic_dist_init(0, __io_address(REALVIEW_DC1176_GIC_DIST_BASE), IRQ_DC1176_GIC_START);
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_init(0, IRQ_DC1176_GIC_START,
+                __io_address(REALVIEW_DC1176_GIC_DIST_BASE),
+                __io_address(REALVIEW_DC1176_GIC_CPU_BASE));
 
        /* board GIC, secondary */
-       gic_dist_init(1, __io_address(REALVIEW_PB1176_GIC_DIST_BASE), IRQ_PB1176_GIC_START);
-       gic_cpu_init(1, __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
+       gic_init(1, IRQ_PB1176_GIC_START,
+                __io_address(REALVIEW_PB1176_GIC_DIST_BASE),
+                __io_address(REALVIEW_PB1176_GIC_CPU_BASE));
        gic_cascade_irq(1, IRQ_DC1176_PB_IRQ1);
 }
 
index 117b95b2ca15c7b4bba1f398934f799fbdec570b..8e8ab7d29a6a0d8b6b020b7ea513e6ec8c96c021 100644 (file)
@@ -309,13 +309,13 @@ static void __init gic_init_irq(void)
        writel(0x00000000, __io_address(REALVIEW_SYS_LOCK));
 
        /* ARM11MPCore test chip GIC, primary */
-       gic_cpu_base_addr = __io_address(REALVIEW_TC11MP_GIC_CPU_BASE);
-       gic_dist_init(0, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE), 29);
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_init(0, 29, __io_address(REALVIEW_TC11MP_GIC_DIST_BASE),
+                __io_address(REALVIEW_TC11MP_GIC_CPU_BASE));
 
        /* board GIC, secondary */
-       gic_dist_init(1, __io_address(REALVIEW_PB11MP_GIC_DIST_BASE), IRQ_PB11MP_GIC_START);
-       gic_cpu_init(1, __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
+       gic_init(1, IRQ_PB11MP_GIC_START,
+                __io_address(REALVIEW_PB11MP_GIC_DIST_BASE),
+                __io_address(REALVIEW_PB11MP_GIC_CPU_BASE));
        gic_cascade_irq(1, IRQ_TC11MP_PB_IRQ1);
 }
 
index 929b8dc12e81754bfb0fdf88f25fa6e4d2664aa6..841118e3e118c7383be126131f8dc5ef125b6461 100644 (file)
@@ -273,9 +273,9 @@ static struct platform_device pmu_device = {
 static void __init gic_init_irq(void)
 {
        /* ARM PB-A8 on-board GIC */
-       gic_cpu_base_addr = __io_address(REALVIEW_PBA8_GIC_CPU_BASE);
-       gic_dist_init(0, __io_address(REALVIEW_PBA8_GIC_DIST_BASE), IRQ_PBA8_GIC_START);
-       gic_cpu_init(0, __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
+       gic_init(0, IRQ_PBA8_GIC_START,
+                __io_address(REALVIEW_PBA8_GIC_DIST_BASE),
+                __io_address(REALVIEW_PBA8_GIC_CPU_BASE));
 }
 
 static void __init realview_pba8_timer_init(void)
index b9f9e20031a75e1ef9442c252849689fa50d486e..02b755b009dbc0c859f0ebf9d98bbf7f6ea96ad9 100644 (file)
@@ -313,15 +313,12 @@ static void __init gic_init_irq(void)
 {
        /* ARM PBX on-board GIC */
        if (core_tile_pbx11mp() || core_tile_pbxa9mp()) {
-               gic_cpu_base_addr = __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE);
-               gic_dist_init(0, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
-                             29);
-               gic_cpu_init(0, __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
+               gic_init(0, 29, __io_address(REALVIEW_PBX_TILE_GIC_DIST_BASE),
+                        __io_address(REALVIEW_PBX_TILE_GIC_CPU_BASE));
        } else {
-               gic_cpu_base_addr = __io_address(REALVIEW_PBX_GIC_CPU_BASE);
-               gic_dist_init(0, __io_address(REALVIEW_PBX_GIC_DIST_BASE),
-                             IRQ_PBX_GIC_START);
-               gic_cpu_init(0, __io_address(REALVIEW_PBX_GIC_CPU_BASE));
+               gic_init(0, IRQ_PBX_GIC_START,
+                        __io_address(REALVIEW_PBX_GIC_DIST_BASE),
+                        __io_address(REALVIEW_PBX_GIC_CPU_BASE));
        }
 }
 
index fa2e5bffbb8eaa37c6d4db06a2213fb476115c64..e82ab4aa7ab942457a9fc5c0a70cfb862c503269 100644 (file)
@@ -28,9 +28,16 @@ config S3C2412_DMA
 
 config S3C2412_PM
        bool
+       select S3C2412_PM_SLEEP
        help
          Internal config node to apply S3C2412 power management
 
+config S3C2412_PM_SLEEP
+       bool
+       help
+         Internal config node to apply sleep for S3C2412 power management.
+         Can be selected by another SoCs with similar sleep procedure.
+
 # Note, the S3C2412 IOtiming support is in plat-s3c24xx
 
 config S3C2412_CPUFREQ
@@ -52,7 +59,7 @@ config MACH_JIVE
          Say Y here if you are using the Logitech Jive.
 
 config MACH_JIVE_SHOW_BOOTLOADER
-       bool "Allow access to bootloader partitions in MTD"
+       bool "Allow access to bootloader partitions in MTD (EXPERIMENTAL)"
        depends on MACH_JIVE && EXPERIMENTAL
 
 config MACH_SMDK2413
index 530ec46cbaea52d9a4ff16c6047450c4029195e4..6c48a91ea39e75a00e29b88a968553fc1e796fbb 100644 (file)
@@ -14,7 +14,8 @@ obj-$(CONFIG_CPU_S3C2412)     += irq.o
 obj-$(CONFIG_CPU_S3C2412)      += clock.o
 obj-$(CONFIG_CPU_S3C2412)      += gpio.o
 obj-$(CONFIG_S3C2412_DMA)      += dma.o
-obj-$(CONFIG_S3C2412_PM)       += pm.o sleep.o
+obj-$(CONFIG_S3C2412_PM)       += pm.o
+obj-$(CONFIG_S3C2412_PM_SLEEP) += sleep.o
 obj-$(CONFIG_S3C2412_CPUFREQ)  += cpu-freq.o
 
 # Machine support
index 27b3e7c9d61366edcdc59f234e563cec3b5b6b2b..df8d14974c90876b31d16ab2a2d2367ef1f7af89 100644 (file)
@@ -27,6 +27,7 @@ config S3C2416_DMA
 
 config S3C2416_PM
        bool
+       select S3C2412_PM_SLEEP
        help
          Internal config node to apply S3C2416 power management
 
index 28677caf3613cca0ec00bf02862ba01c049fd6fd..461aa035afc05956a6262ea53921a941bf757b84 100644 (file)
@@ -378,6 +378,12 @@ static struct max8998_regulator_data aquila_regulators[] = {
 static struct max8998_platform_data aquila_max8998_pdata = {
        .num_regulators = ARRAY_SIZE(aquila_regulators),
        .regulators     = aquila_regulators,
+       .buck1_set1     = S5PV210_GPH0(3),
+       .buck1_set2     = S5PV210_GPH0(4),
+       .buck2_set3     = S5PV210_GPH0(5),
+       .buck1_max_voltage1 = 1200000,
+       .buck1_max_voltage2 = 1200000,
+       .buck2_max_voltage = 1200000,
 };
 #endif
 
index b1dcf964a768773772659b7a01b9e3b6cb8de545..e22d5112fd44aa3267c3bee3a23b023331b951cd 100644 (file)
@@ -518,6 +518,12 @@ static struct max8998_regulator_data goni_regulators[] = {
 static struct max8998_platform_data goni_max8998_pdata = {
        .num_regulators = ARRAY_SIZE(goni_regulators),
        .regulators     = goni_regulators,
+       .buck1_set1     = S5PV210_GPH0(3),
+       .buck1_set2     = S5PV210_GPH0(4),
+       .buck2_set3     = S5PV210_GPH0(5),
+       .buck1_max_voltage1 = 1200000,
+       .buck1_max_voltage2 = 1200000,
+       .buck2_max_voltage = 1200000,
 };
 #endif
 
index 82ce4aa6d61a5c07f004f26cc08e11d80f583b0d..72ab289e78166bfb102f6e4e46dc44cfb7f548ac 100644 (file)
@@ -24,8 +24,6 @@
 
 #include <mach/regs-irq.h>
 
-void __iomem *gic_cpu_base_addr;
-
 extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
                         unsigned int irq_start);
 extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
@@ -122,9 +120,7 @@ void __init s5pv310_init_irq(void)
 {
        int irq;
 
-       gic_cpu_base_addr = S5P_VA_GIC_CPU;
-       gic_dist_init(0, S5P_VA_GIC_DIST, IRQ_LOCALTIMER);
-       gic_cpu_init(0, S5P_VA_GIC_CPU);
+       gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
 
        for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
                combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
index 03652c3605f602e00c9233a54c3936dac627a65a..afa5392d9fc0ed3900562e6fd2125b3e3ff990cd 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
        unsigned int v;
@@ -33,13 +30,13 @@ static inline void cpu_enter_lowpower(void)
         * Turn off coherency
         */
        "       mrc     p15, 0, %0, c1, c0, 1\n"
-       "       bic     %0, %0, #0x20\n"
+       "       bic     %0, %0, %2\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
        "       mrc     p15, 0, %0, c1, c0, 0\n"
        "       bic     %0, %0, #0x04\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
          : "=&r" (v)
-         : "r" (0)
+         : "r" (0), "Ir" (CR_C)
          : "cc");
 }
 
@@ -49,17 +46,17 @@ static inline void cpu_leave_lowpower(void)
 
        asm volatile(
        "mrc    p15, 0, %0, c1, c0, 0\n"
-       "       orr     %0, %0, #0x04\n"
+       "       orr     %0, %0, %1\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
        "       mrc     p15, 0, %0, c1, c0, 1\n"
        "       orr     %0, %0, #0x20\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
          : "=&r" (v)
-         :
+         : "Ir" (CR_C)
          : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
        /*
         * there is no power-control hardware on this platform, so all
@@ -83,22 +80,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
                }
 
                /*
-                * getting here, means that we have come out of WFI without
+                * Getting here, means that we have come out of WFI without
                 * having been woken up - this shouldn't happen
                 *
-                * The trouble is, letting people know about this is not really
-                * possible, since we are currently running incoherently, and
-                * therefore cannot safely call printk() or anything else
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
                 */
-#ifdef DEBUG
-               printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
-#endif
+               (*spurious)++;
        }
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -108,30 +102,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-#endif
-
-       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
+       int spurious = 0;
 
        /*
         * we're ready for shutdown now, so do it
         */
        cpu_enter_lowpower();
-       platform_do_lowpower(cpu);
+       platform_do_lowpower(cpu, &spurious);
 
        /*
         * bring this CPU back into the world of cache
         * coherency, and then restore interrupts
         */
        cpu_leave_lowpower();
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
 
 int platform_cpu_disable(unsigned int cpu)
index b7ec252384f47059f681ddad95c1d183ad8b39dc..393ccbd52c4ac2d87d715f34413b9a4aeddce475 100644 (file)
@@ -7,16 +7,13 @@
 #define ASM_ARCH_SMP_H __FILE__
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
-
-extern void __iomem *gic_cpu_base_addr;
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index d357c198edee308112bc3633256376ca69720abb..34093b069f6759eec861c2031421cfa78160bd86 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <asm/unified.h>
 
@@ -38,6 +37,19 @@ extern void s5pv310_secondary_startup(void);
 
 volatile int __cpuinitdata pen_release = -1;
 
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+       pen_release = val;
+       smp_wmb();
+       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
 static void __iomem *scu_base_addr(void)
 {
        return (void __iomem *)(S5P_VA_SCU);
@@ -47,21 +59,18 @@ static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_secondary_init(0);
 
        /*
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
-       pen_release = -1;
-       smp_wmb();
+       write_pen_release(-1);
 
        /*
         * Synchronise with the boot thread.
@@ -88,16 +97,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * Note that "pen_release" is the hardware CPU ID, whereas
         * "cpu" is Linux's internal ID.
         */
-       pen_release = cpu;
-       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+       write_pen_release(cpu);
 
        /*
         * Send the secondary CPU a soft interrupt, thereby causing
         * the boot monitor to read the system wide flags register,
         * and branch to the address found there.
         */
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
@@ -130,13 +137,6 @@ void __init smp_init_cpus(void)
        ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "S5PV310: strange CM count of 0? Default to 1\n");
-
-               ncores = 1;
-       }
-
        if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "S5PV310: no. of cores (%d) greater than configured "
@@ -149,18 +149,10 @@ void __init smp_init_cpus(void)
                set_cpu_possible(i, true);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned int ncores = num_possible_cpus();
-       unsigned int cpu = smp_processor_id();
        int i;
 
-       smp_store_cpu_info(cpu);
-
-       /* are we trying to boot more cores than exist? */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
-
        /*
         * Initialise the present map, which describes the set of CPUs
         * actually populated at the present time.
@@ -168,25 +160,13 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
+       scu_enable(scu_base_addr());
+
        /*
-        * Initialise the SCU if there are more than one CPU and let
-        * them know where to start.
+        * Write the address of secondary startup into the
+        * system-wide flags register. The boot monitor waits
+        * until it receives a soft interrupt, and then the
+        * secondary CPU branches to this address.
         */
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-
-               scu_enable(scu_base_addr());
-
-               /*
-                * Write the address of secondary startup into the
-                * system-wide flags register. The boot monitor waits
-                * until it receives a soft interrupt, and then the
-                * secondary CPU branches to this address.
-                */
        __raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM);
-       }
 }
index 01b012ad1bfd76fd4de187742a753d68d9ecb0fe..b262d4615331c8a4bfc513c5d1ebf62feac5d5e4 100644 (file)
@@ -211,7 +211,6 @@ struct clocksource pwm_clocksource = {
        .rating         = 250,
        .read           = s5pv310_pwm4_read,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS ,
 };
 
@@ -230,10 +229,7 @@ static void __init s5pv310_clocksource_init(void)
        s5pv310_pwm_init(4, ~0);
        s5pv310_pwm_start(4, 1);
 
-       pwm_clocksource.mult =
-               clocksource_khz2mult(clock_rate/1000, pwm_clocksource.shift);
-
-       if (clocksource_register(&pwm_clocksource))
+       if (clocksource_register_hz(&pwm_clocksource, clock_rate))
                panic("%s: can't register clocksource\n", pwm_clocksource.name);
 }
 
index 5da8c35aa0de14f89159a24e2f05a0edc451c01b..42625e4d949a143f828ba96c155754f422aa0d65 100644 (file)
@@ -118,6 +118,16 @@ config SA1100_LART
          (also known as the LART).  See <http://www.lartmaker.nl/> for
          information on the LART.
 
+config SA1100_NANOENGINE
+       bool "nanoEngine"
+       select CPU_FREQ_SA1110
+       select PCI
+       select PCI_NANOENGINE
+       help
+         Say Y here if you are using the Bright Star Engineering nanoEngine.
+         See <http://www.brightstareng.com/arm/nanoeng.htm> for information
+         on the BSE nanoEngine.
+
 config SA1100_PLEB
        bool "PLEB"
        select CPU_FREQ_SA1100
index 89349c1dd7a69b2639fe2277a6622f6aa8324b44..e697691eed283bfd1a81681c8a784328d4aa6ba5 100644 (file)
@@ -37,6 +37,9 @@ obj-$(CONFIG_SA1100_JORNADA720_SSP)   += jornada720_ssp.o
 obj-$(CONFIG_SA1100_LART)              += lart.o
 led-$(CONFIG_SA1100_LART)              += leds-lart.o
 
+obj-$(CONFIG_SA1100_NANOENGINE)                += nanoengine.o
+obj-$(CONFIG_PCI_NANOENGINE)           += pci-nanoengine.o
+
 obj-$(CONFIG_SA1100_PLEB)              += pleb.o
 
 obj-$(CONFIG_SA1100_SHANNON)           += shannon.o
index 96f7dc103b5987c586a663a9e19729027f832e70..07d4e8ba37191606f980ed2bc6dbf03def722c9a 100644 (file)
 
 #include "generic.h"
 
-typedef struct {
+struct sa1100_dram_regs {
        int speed;
        u32 mdcnfg;
        u32 mdcas0;
        u32 mdcas1;
        u32 mdcas2;
-} sa1100_dram_regs_t;
+};
 
 
 static struct cpufreq_driver sa1100_driver;
 
-static sa1100_dram_regs_t sa1100_dram_settings[] =
-{
-       /* speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2  clock frequency */
-       {  59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  59.0 MHz */
-       {  73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  73.7 MHz */
-       {  88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff }, /*  88.5 MHz */
-       { 103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff }, /* 103.2 MHz */
-       { 118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 118.0 MHz */
-       { 132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff }, /* 132.7 MHz */
-       { 147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff }, /* 147.5 MHz */
-       { 162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff }, /* 162.2 MHz */
-       { 176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff }, /* 176.9 MHz */
-       { 191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff }, /* 191.7 MHz */
-       { 206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 206.4 MHz */
-       { 221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff }, /* 221.2 MHz */
-       { 235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1 }, /* 235.9 MHz */
-       { 250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 250.7 MHz */
-       { 265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3 }, /* 265.4 MHz */
-       { 280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87 }, /* 280.2 MHz */
+static struct sa1100_dram_regs sa1100_dram_settings[] = {
+       /*speed,     mdcnfg,     mdcas0,     mdcas1,     mdcas2,   clock freq */
+       { 59000, 0x00dc88a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  59.0 MHz */
+       { 73700, 0x011490a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  73.7 MHz */
+       { 88500, 0x014e90a3, 0xcccccccf, 0xfffffffc, 0xffffffff},/*  88.5 MHz */
+       {103200, 0x01889923, 0xcccccccf, 0xfffffffc, 0xffffffff},/* 103.2 MHz */
+       {118000, 0x01c29923, 0x9999998f, 0xfffffff9, 0xffffffff},/* 118.0 MHz */
+       {132700, 0x01fb2123, 0x9999998f, 0xfffffff9, 0xffffffff},/* 132.7 MHz */
+       {147500, 0x02352123, 0x3333330f, 0xfffffff3, 0xffffffff},/* 147.5 MHz */
+       {162200, 0x026b29a3, 0x38e38e1f, 0xfff8e38e, 0xffffffff},/* 162.2 MHz */
+       {176900, 0x02a329a3, 0x71c71c1f, 0xfff1c71c, 0xffffffff},/* 176.9 MHz */
+       {191700, 0x02dd31a3, 0xe38e383f, 0xffe38e38, 0xffffffff},/* 191.7 MHz */
+       {206400, 0x03153223, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 206.4 MHz */
+       {221200, 0x034fba23, 0xc71c703f, 0xffc71c71, 0xffffffff},/* 221.2 MHz */
+       {235900, 0x03853a23, 0xe1e1e07f, 0xe1e1e1e1, 0xffffffe1},/* 235.9 MHz */
+       {250700, 0x03bf3aa3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 250.7 MHz */
+       {265400, 0x03f7c2a3, 0xc3c3c07f, 0xc3c3c3c3, 0xffffffc3},/* 265.4 MHz */
+       {280200, 0x0431c2a3, 0x878780ff, 0x87878787, 0xffffff87},/* 280.2 MHz */
        { 0, 0, 0, 0, 0 } /* last entry */
 };
 
 static void sa1100_update_dram_timings(int current_speed, int new_speed)
 {
-       sa1100_dram_regs_t *settings = sa1100_dram_settings;
+       struct sa1100_dram_regs *settings = sa1100_dram_settings;
 
        /* find speed */
        while (settings->speed != 0) {
-               if(new_speed == settings->speed)
+               if (new_speed == settings->speed)
                        break;
-               
+
                settings++;
        }
 
@@ -149,7 +148,7 @@ static void sa1100_update_dram_timings(int current_speed, int new_speed)
                /* We're going FASTER, so first relax the memory
                 * timings before changing the core frequency
                 */
-               
+
                /* Half the memory access clock */
                MDCNFG |= MDCNFG_CDB2;
 
@@ -187,7 +186,7 @@ static int sa1100_target(struct cpufreq_policy *policy,
        struct cpufreq_freqs freqs;
 
        new_ppcr = sa11x0_freq_to_ppcr(target_freq);
-       switch(relation){
+       switch (relation) {
        case CPUFREQ_RELATION_L:
                if (sa11x0_ppcr_to_freq(new_ppcr) > policy->max)
                        new_ppcr--;
index 7252874d328b59eb808110351aabeff2e4a9c11d..675bf8ef97e8061fbc0041ce2a5ac620d048cc95 100644 (file)
  *
  * The SDRAM type can be passed on the command line as cpu_sa1110.sdram=type
  */
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
 #include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/init.h>
-#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
 
-#include <mach/hardware.h>
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
-#include <asm/system.h>
+
+#include <mach/hardware.h>
 
 #include "generic.h"
 
 #undef DEBUG
 
-static struct cpufreq_driver sa1110_driver;
-
 struct sdram_params {
-       const char name[16];
+       const char name[20];
        u_char  rows;           /* bits                          */
        u_char  cas_latency;    /* cycles                        */
        u_char  tck;            /* clock cycle time (ns)         */
@@ -107,6 +103,15 @@ static struct sdram_params sdram_tbl[] __initdata = {
                .twr            = 8,
                .refresh        = 64000,
                .cas_latency    = 3,
+       }, {    /* Micron MT48LC8M16A2TG-75 */
+               .name           = "MT48LC8M16A2TG-75",
+               .rows           = 12,
+               .tck            = 8,
+               .trcd           = 20,
+               .trp            = 20,
+               .twr            = 8,
+               .refresh        = 64000,
+               .cas_latency    = 3,
        },
 };
 
@@ -180,11 +185,13 @@ sdram_calculate_timing(struct sdram_info *sd, u_int cpu_khz,
                sd->mdrefr |= MDREFR_K1DB2;
 
        /* initial number of '1's in MDCAS + 1 */
-       set_mdcas(sd->mdcas, sd_khz >= 62000, ns_to_cycles(sdram->trcd, mem_khz));
+       set_mdcas(sd->mdcas, sd_khz >= 62000,
+               ns_to_cycles(sdram->trcd, mem_khz));
 
 #ifdef DEBUG
-       printk("MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
-               sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1], sd->mdcas[2]);
+       printk(KERN_DEBUG "MDCNFG: %08x MDREFR: %08x MDCAS0: %08x MDCAS1: %08x MDCAS2: %08x\n",
+               sd->mdcnfg, sd->mdrefr, sd->mdcas[0], sd->mdcas[1],
+               sd->mdcas[2]);
 #endif
 }
 
@@ -213,7 +220,7 @@ sdram_update_refresh(u_int cpu_khz, struct sdram_params *sdram)
 
 #ifdef DEBUG
        mdelay(250);
-       printk("new dri value = %d\n", dri);
+       printk(KERN_DEBUG "new dri value = %d\n", dri);
 #endif
 
        sdram_set_refresh(dri);
@@ -232,7 +239,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
        unsigned long flags;
        unsigned int ppcr, unused;
 
-       switch(relation){
+       switch (relation) {
        case CPUFREQ_RELATION_L:
                ppcr = sa11x0_freq_to_ppcr(target_freq);
                if (sa11x0_ppcr_to_freq(ppcr) > policy->max)
@@ -280,11 +287,10 @@ static int sa1110_target(struct cpufreq_policy *policy,
         * We wait 20ms to be safe.
         */
        sdram_set_refresh(2);
-       if (!irqs_disabled()) {
+       if (!irqs_disabled())
                msleep(20);
-       } else {
+       else
                mdelay(20);
-       }
 
        /*
         * Reprogram the DRAM timings with interrupts disabled, and
@@ -295,7 +301,7 @@ static int sa1110_target(struct cpufreq_policy *policy,
        local_irq_save(flags);
        asm("mcr p15, 0, %0, c7, c10, 4" : : "r" (0));
        udelay(10);
-       __asm__ __volatile__("                                  \n\
+       __asm__ __volatile__("\n\
                b       2f                                      \n\
                .align  5                                       \n\
 1:             str     %3, [%1, #0]            @ MDCNFG        \n\
@@ -336,7 +342,9 @@ static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
        return 0;
 }
 
-static struct cpufreq_driver sa1110_driver = {
+/* sa1110_driver needs __refdata because it must remain after init registers
+ * it with cpufreq_register_driver() */
+static struct cpufreq_driver sa1110_driver __refdata = {
        .flags          = CPUFREQ_STICKY,
        .verify         = sa11x0_verify_speed,
        .target         = sa1110_target,
@@ -349,7 +357,8 @@ static struct sdram_params *sa1110_find_sdram(const char *name)
 {
        struct sdram_params *sdram;
 
-       for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl); sdram++)
+       for (sdram = sdram_tbl; sdram < sdram_tbl + ARRAY_SIZE(sdram_tbl);
+            sdram++)
                if (strcmp(name, sdram->name) == 0)
                        return sdram;
 
@@ -369,14 +378,14 @@ static int __init sa1110_clk_init(void)
        if (!name[0]) {
                if (machine_is_assabet())
                        name = "TC59SM716-CL3";
-
                if (machine_is_pt_system3())
                        name = "K4S641632D";
-
                if (machine_is_h3100())
                        name = "KM416S4030CT";
                if (machine_is_jornada720())
-                       name = "K4S281632B-1H";
+                       name = "K4S281632B-1H";
+               if (machine_is_nanoengine())
+                       name = "MT48LC8M16A2TG-75";
        }
 
        sdram = sa1110_find_sdram(name);
index 3c1fcd6967145cc91a04752db09c856d031f4e49..59d14f0fdcf8d1af2c5d5f837cc70bba37be99f8 100644 (file)
@@ -16,9 +16,7 @@
 #include <linux/pm.h>
 #include <linux/cpufreq.h>
 #include <linux/ioport.h>
-#include <linux/sched.h>       /* just for sched_clock() - funny that */
 #include <linux/platform_device.h>
-#include <linux/cnt32_to_63.h>
 
 #include <asm/div64.h>
 #include <mach/hardware.h>
@@ -109,27 +107,6 @@ unsigned int sa11x0_getspeed(unsigned int cpu)
        return cclk_frequency_100khz[PPCR & 0xf] * 100;
 }
 
-/*
- * This is the SA11x0 sched_clock implementation.  This has
- * a resolution of 271ns, and a maximum value of 32025597s (370 days).
- *
- * The return value is guaranteed to be monotonic in that range as
- * long as there is always less than 582 seconds between successive
- * calls to this function.
- *
- *  ( * 1E9 / 3686400 => * 78125 / 288)
- */
-unsigned long long sched_clock(void)
-{
-       unsigned long long v = cnt32_to_63(OSCR);
-
-       /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */
-       v *= 78125<<1;
-       do_div(v, 288<<1);
-
-       return v;
-}
-
 /*
  * Default power-off for SA1100
  */
@@ -163,10 +140,15 @@ static void sa11x0_register_device(struct platform_device *dev, void *data)
 
 static struct resource sa11x0udc_resources[] = {
        [0] = {
-               .start  = 0x80000000,
-               .end    = 0x8000ffff,
+               .start  = __PREG(Ser0UDCCR),
+               .end    = __PREG(Ser0UDCCR) + 0xffff,
                .flags  = IORESOURCE_MEM,
        },
+       [1] = {
+               .start  = IRQ_Ser0UDC,
+               .end    = IRQ_Ser0UDC,
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
 static u64 sa11x0udc_dma_mask = 0xffffffffUL;
@@ -184,10 +166,15 @@ static struct platform_device sa11x0udc_device = {
 
 static struct resource sa11x0uart1_resources[] = {
        [0] = {
-               .start  = 0x80010000,
-               .end    = 0x8001ffff,
+               .start  = __PREG(Ser1UTCR0),
+               .end    = __PREG(Ser1UTCR0) + 0xffff,
                .flags  = IORESOURCE_MEM,
        },
+       [1] = {
+               .start  = IRQ_Ser1UART,
+               .end    = IRQ_Ser1UART,
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
 static struct platform_device sa11x0uart1_device = {
@@ -199,10 +186,15 @@ static struct platform_device sa11x0uart1_device = {
 
 static struct resource sa11x0uart3_resources[] = {
        [0] = {
-               .start  = 0x80050000,
-               .end    = 0x8005ffff,
+               .start  = __PREG(Ser3UTCR0),
+               .end    = __PREG(Ser3UTCR0) + 0xffff,
                .flags  = IORESOURCE_MEM,
        },
+       [1] = {
+               .start  = IRQ_Ser3UART,
+               .end    = IRQ_Ser3UART,
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
 static struct platform_device sa11x0uart3_device = {
@@ -214,10 +206,15 @@ static struct platform_device sa11x0uart3_device = {
 
 static struct resource sa11x0mcp_resources[] = {
        [0] = {
-               .start  = 0x80060000,
-               .end    = 0x8006ffff,
+               .start  = __PREG(Ser4MCCR0),
+               .end    = __PREG(Ser4MCCR0) + 0xffff,
                .flags  = IORESOURCE_MEM,
        },
+       [1] = {
+               .start  = IRQ_Ser4MCP,
+               .end    = IRQ_Ser4MCP,
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
 static u64 sa11x0mcp_dma_mask = 0xffffffffUL;
@@ -244,6 +241,11 @@ static struct resource sa11x0ssp_resources[] = {
                .end    = 0x8007ffff,
                .flags  = IORESOURCE_MEM,
        },
+       [1] = {
+               .start  = IRQ_Ser4SSP,
+               .end    = IRQ_Ser4SSP,
+               .flags  = IORESOURCE_IRQ,
+       },
 };
 
 static u64 sa11x0ssp_dma_mask = 0xffffffffUL;
index 99f5856d8de424ce006d09c090cf0810f649e811..967ae7684390b5b12488af416a4b6eac2ac78776 100644 (file)
@@ -76,4 +76,12 @@ static inline unsigned long get_clock_tick_rate(void)
 #include "SA-1101.h"
 #endif
 
+#if defined(CONFIG_ARCH_SA1100) && defined(CONFIG_PCI)
+#define PCIBIOS_MIN_IO         0
+#define PCIBIOS_MIN_MEM                0
+#define pcibios_assign_all_busses()    1
+#define HAVE_ARCH_PCI_SET_DMA_MASK     1
+#endif
+
+
 #endif  /* _ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-sa1100/include/mach/nanoengine.h b/arch/arm/mach-sa1100/include/mach/nanoengine.h
new file mode 100644 (file)
index 0000000..14f8382
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * arch/arm/mach-sa1100/include/mach/nanoengine.h
+ *
+ * This file contains the hardware specific definitions for nanoEngine.
+ * Only include this file from SA1100-specific files.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#ifndef __ASM_ARCH_NANOENGINE_H
+#define __ASM_ARCH_NANOENGINE_H
+
+#include <mach/irqs.h>
+
+#define GPIO_PC_READY0 GPIO_GPIO(11) /* ready for socket 0 (active high)*/
+#define GPIO_PC_READY1 GPIO_GPIO(12) /* ready for socket 1 (active high) */
+#define GPIO_PC_CD0    GPIO_GPIO(13) /* detect for socket 0 (active low) */
+#define GPIO_PC_CD1    GPIO_GPIO(14) /* detect for socket 1 (active low) */
+#define GPIO_PC_RESET0 GPIO_GPIO(15) /* reset socket 0 */
+#define GPIO_PC_RESET1 GPIO_GPIO(16) /* reset socket 1 */
+
+#define NANOENGINE_IRQ_GPIO_PCI                IRQ_GPIO0
+#define NANOENGINE_IRQ_GPIO_PC_READY0  IRQ_GPIO11
+#define NANOENGINE_IRQ_GPIO_PC_READY1  IRQ_GPIO12
+#define NANOENGINE_IRQ_GPIO_PC_CD0     IRQ_GPIO13
+#define NANOENGINE_IRQ_GPIO_PC_CD1     IRQ_GPIO14
+
+/*
+ * nanoEngine Memory Map:
+ *
+ * 0000.0000 - 003F.0000 -   4 MB Flash
+ * C000.0000 - C1FF.FFFF -  32 MB SDRAM
+ * 1860.0000 - 186F.FFFF -   1 MB Internal PCI Memory Read/Write
+ * 18A1.0000 - 18A1.FFFF -  64 KB Internal PCI Config Space
+ * 4000.0000 - 47FF.FFFF - 128 MB External Bus I/O - Multiplexed Mode
+ * 4800.0000 - 4FFF.FFFF - 128 MB External Bus I/O - Non-Multiplexed Mode
+ *
+ */
+
+#define NANO_PCI_MEM_RW_PHYS           0x18600000
+#define NANO_PCI_MEM_RW_VIRT           0xf1000000
+#define NANO_PCI_MEM_RW_SIZE           SZ_1M
+#define NANO_PCI_CONFIG_SPACE_PHYS     0x18A10000
+#define NANO_PCI_CONFIG_SPACE_VIRT     0xf2000000
+#define NANO_PCI_CONFIG_SPACE_SIZE     SZ_64K
+
+#endif
+
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
new file mode 100644 (file)
index 0000000..72087f0
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * linux/arch/arm/mach-sa1100/nanoengine.c
+ *
+ * Bright Star Engineering's nanoEngine board init code.
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/root_dev.h>
+
+#include <asm/mach-types.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/flash.h>
+#include <asm/mach/map.h>
+#include <asm/mach/serial_sa1100.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "generic.h"
+
+/* Flash bank 0 */
+static struct mtd_partition nanoengine_partitions[] = {
+       {
+               .name   = "nanoEngine boot firmware and parameter table",
+               .size           = 0x00010000,  /* 32K */
+               .offset         = 0,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "kernel/initrd reserved",
+               .size           = 0x002f0000,
+               .offset         = 0x00010000,
+               .mask_flags     = MTD_WRITEABLE,
+       }, {
+               .name           = "experimental filesystem allocation",
+               .size           = 0x00100000,
+               .offset         = 0x00300000,
+               .mask_flags     = MTD_WRITEABLE,
+       }
+};
+
+static struct flash_platform_data nanoengine_flash_data = {
+       .map_name       = "jedec_probe",
+       .parts          = nanoengine_partitions,
+       .nr_parts       = ARRAY_SIZE(nanoengine_partitions),
+};
+
+static struct resource nanoengine_flash_resources[] = {
+       {
+               .start  = SA1100_CS0_PHYS,
+               .end    = SA1100_CS0_PHYS + SZ_32M - 1,
+               .flags  = IORESOURCE_MEM,
+       }, {
+               .start  = SA1100_CS1_PHYS,
+               .end    = SA1100_CS1_PHYS + SZ_32M - 1,
+               .flags  = IORESOURCE_MEM,
+       }
+};
+
+static struct map_desc nanoengine_io_desc[] __initdata = {
+       {
+               /* System Registers */
+               .virtual        = 0xf0000000,
+               .pfn            = __phys_to_pfn(0x10000000),
+               .length         = 0x00100000,
+               .type           = MT_DEVICE
+       }, {
+               /* Internal PCI Memory Read/Write */
+               .virtual        = NANO_PCI_MEM_RW_VIRT,
+               .pfn            = __phys_to_pfn(NANO_PCI_MEM_RW_PHYS),
+               .length         = NANO_PCI_MEM_RW_SIZE,
+               .type           = MT_DEVICE
+       }, {
+               /* Internal PCI Config Space */
+               .virtual        = NANO_PCI_CONFIG_SPACE_VIRT,
+               .pfn            = __phys_to_pfn(NANO_PCI_CONFIG_SPACE_PHYS),
+               .length         = NANO_PCI_CONFIG_SPACE_SIZE,
+               .type           = MT_DEVICE
+       }
+};
+
+static void __init nanoengine_map_io(void)
+{
+       sa1100_map_io();
+       iotable_init(nanoengine_io_desc, ARRAY_SIZE(nanoengine_io_desc));
+
+       sa1100_register_uart(0, 1);
+       sa1100_register_uart(1, 2);
+       sa1100_register_uart(2, 3);
+       Ser1SDCR0 |= SDCR0_UART;
+       /* disable IRDA -- UART2 is used as a normal serial port */
+       Ser2UTCR4 = 0;
+       Ser2HSCR0 = 0;
+}
+
+static void __init nanoengine_init(void)
+{
+       sa11x0_register_mtd(&nanoengine_flash_data, nanoengine_flash_resources,
+               ARRAY_SIZE(nanoengine_flash_resources));
+}
+
+MACHINE_START(NANOENGINE, "BSE nanoEngine")
+       .boot_params    = 0xc0000000,
+       .map_io         = nanoengine_map_io,
+       .init_irq       = sa1100_init_irq,
+       .timer          = &sa1100_timer,
+       .init_machine   = nanoengine_init,
+MACHINE_END
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c
new file mode 100644 (file)
index 0000000..fba7a91
--- /dev/null
@@ -0,0 +1,284 @@
+/*
+ * linux/arch/arm/mach-sa1100/pci-nanoengine.c
+ *
+ * PCI functions for BSE nanoEngine PCI
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * 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/kernel.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+
+#include <asm/mach/pci.h>
+#include <asm/mach-types.h>
+
+#include <mach/nanoengine.h>
+
+static DEFINE_SPINLOCK(nano_lock);
+
+static int nanoengine_get_pci_address(struct pci_bus *bus,
+       unsigned int devfn, int where, unsigned long *address)
+{
+       int ret = PCIBIOS_DEVICE_NOT_FOUND;
+       unsigned int busnr = bus->number;
+
+       *address = NANO_PCI_CONFIG_SPACE_VIRT +
+               ((bus->number << 16) | (devfn << 8) | (where & ~3));
+
+       ret = (busnr > 255 || devfn > 255 || where > 255) ?
+               PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL;
+
+       return ret;
+}
+
+static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+       int size, u32 *val)
+{
+       int ret;
+       unsigned long address;
+       unsigned long flags;
+       u32 v;
+
+       /* nanoEngine PCI bridge does not return -1 for a non-existing
+        * device. We must fake the answer. We know that the only valid
+        * device is device zero at bus 0, which is the network chip. */
+       if (bus->number != 0 || (devfn >> 3) != 0) {
+               v = -1;
+               nanoengine_get_pci_address(bus, devfn, where, &address);
+               goto exit_function;
+       }
+
+       spin_lock_irqsave(&nano_lock, flags);
+
+       ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+       if (ret != PCIBIOS_SUCCESSFUL)
+               return ret;
+       v = __raw_readl(address);
+
+       spin_unlock_irqrestore(&nano_lock, flags);
+
+       v >>= ((where & 3) * 8);
+       v &= (unsigned long)(-1) >> ((4 - size) * 8);
+
+exit_function:
+       *val = v;
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+       int size, u32 val)
+{
+       int ret;
+       unsigned long address;
+       unsigned long flags;
+       unsigned shift;
+       u32 v;
+
+       shift = (where & 3) * 8;
+
+       spin_lock_irqsave(&nano_lock, flags);
+
+       ret = nanoengine_get_pci_address(bus, devfn, where, &address);
+       if (ret != PCIBIOS_SUCCESSFUL)
+               return ret;
+       v = __raw_readl(address);
+       switch (size) {
+       case 1:
+               v &= ~(0xFF << shift);
+               v |= val << shift;
+               break;
+       case 2:
+               v &= ~(0xFFFF << shift);
+               v |= val << shift;
+               break;
+       case 4:
+               v = val;
+               break;
+       }
+       __raw_writel(v, address);
+
+       spin_unlock_irqrestore(&nano_lock, flags);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_nano_ops = {
+       .read   = nanoengine_read_config,
+       .write  = nanoengine_write_config,
+};
+
+static int __init pci_nanoengine_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+       return NANOENGINE_IRQ_GPIO_PCI;
+}
+
+struct pci_bus * __init pci_nanoengine_scan_bus(int nr, struct pci_sys_data *sys)
+{
+       return pci_scan_bus(sys->busnr, &pci_nano_ops, sys);
+}
+
+static struct resource pci_io_ports = {
+       .name   = "PCI IO",
+       .start  = 0x400,
+       .end    = 0x7FF,
+       .flags  = IORESOURCE_IO,
+};
+
+static struct resource pci_non_prefetchable_memory = {
+       .name   = "PCI non-prefetchable",
+       .start  = NANO_PCI_MEM_RW_PHYS,
+       /* nanoEngine documentation says there is a 1 Megabyte window here,
+        * but PCI reports just 128 + 8 kbytes. */
+       .end    = NANO_PCI_MEM_RW_PHYS + NANO_PCI_MEM_RW_SIZE - 1,
+/*     .end    = NANO_PCI_MEM_RW_PHYS + SZ_128K + SZ_8K - 1,*/
+       .flags  = IORESOURCE_MEM,
+};
+
+/*
+ * nanoEngine PCI reports 1 Megabyte of prefetchable memory, but it
+ * overlaps with previously defined memory.
+ *
+ * Here is what happens:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: can't assign mem pref (size 0x100000)
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
+ *
+ * On the other hand, if we do not request the prefetchable memory resource,
+ * linux will alloc it first and the two non-prefetchable memory areas that
+ * are our real interest will not be mapped. So we choose to map it to an
+ * unused area. It gets recognized as expansion ROM, but becomes disabled.
+ *
+ * Here is what happens then:
+ *
+# dmesg
+...
+pci 0000:00:00.0: [8086:1209] type 0 class 0x000200
+pci 0000:00:00.0: reg 10: [mem 0x00021000-0x00021fff]
+pci 0000:00:00.0: reg 14: [io  0x0000-0x003f]
+pci 0000:00:00.0: reg 18: [mem 0x00000000-0x0001ffff]
+pci 0000:00:00.0: reg 30: [mem 0x00000000-0x000fffff pref]
+pci 0000:00:00.0: supports D1 D2
+pci 0000:00:00.0: PME# supported from D0 D1 D2 D3hot
+pci 0000:00:00.0: PME# disabled
+PCI: bus0: Fast back to back transfers enabled
+pci 0000:00:00.0: BAR 6: assigned [mem 0x78000000-0x780fffff pref]
+pci 0000:00:00.0: BAR 2: assigned [mem 0x18600000-0x1861ffff]
+pci 0000:00:00.0: BAR 2: set to [mem 0x18600000-0x1861ffff] (PCI address [0x0-0x1ffff])
+pci 0000:00:00.0: BAR 0: assigned [mem 0x18620000-0x18620fff]
+pci 0000:00:00.0: BAR 0: set to [mem 0x18620000-0x18620fff] (PCI address [0x20000-0x20fff])
+pci 0000:00:00.0: BAR 1: assigned [io  0x0400-0x043f]
+pci 0000:00:00.0: BAR 1: set to [io  0x0400-0x043f] (PCI address [0x0-0x3f])
+
+# lspci -vv -s 0000:00:00.0
+00:00.0 Class 0200: Device 8086:1209 (rev 09)
+        Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr+ Stepping- SERR+ FastB2B- DisINTx-
+        Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR+ <PERR+ INTx-
+        Latency: 0 (2000ns min, 14000ns max), Cache Line Size: 32 bytes
+        Interrupt: pin A routed to IRQ 0
+        Region 0: Memory at 18620000 (32-bit, non-prefetchable) [size=4K]
+        Region 1: I/O ports at 0400 [size=64]
+        Region 2: [virtual] Memory at 18600000 (32-bit, non-prefetchable) [size=128K]
+        [virtual] Expansion ROM at 78000000 [disabled] [size=1M]
+        Capabilities: [dc] Power Management version 2
+                Flags: PMEClk- DSI+ D1+ D2+ AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold-)
+                Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=2 PME-
+        Kernel driver in use: e100
+        Kernel modules: e100
+ *
+ */
+static struct resource pci_prefetchable_memory = {
+       .name   = "PCI prefetchable",
+       .start  = 0x78000000,
+       .end    = 0x78000000 + NANO_PCI_MEM_RW_SIZE - 1,
+       .flags  = IORESOURCE_MEM  | IORESOURCE_PREFETCH,
+};
+
+static int __init pci_nanoengine_setup_resources(struct resource **resource)
+{
+       if (request_resource(&ioport_resource, &pci_io_ports)) {
+               printk(KERN_ERR "PCI: unable to allocate io port region\n");
+               return -EBUSY;
+       }
+       if (request_resource(&iomem_resource, &pci_non_prefetchable_memory)) {
+               release_resource(&pci_io_ports);
+               printk(KERN_ERR "PCI: unable to allocate non prefetchable\n");
+               return -EBUSY;
+       }
+       if (request_resource(&iomem_resource, &pci_prefetchable_memory)) {
+               release_resource(&pci_io_ports);
+               release_resource(&pci_non_prefetchable_memory);
+               printk(KERN_ERR "PCI: unable to allocate prefetchable\n");
+               return -EBUSY;
+       }
+       resource[0] = &pci_io_ports;
+       resource[1] = &pci_non_prefetchable_memory;
+       resource[2] = &pci_prefetchable_memory;
+
+       return 1;
+}
+
+int __init pci_nanoengine_setup(int nr, struct pci_sys_data *sys)
+{
+       int ret = 0;
+
+       if (nr == 0) {
+               sys->mem_offset = NANO_PCI_MEM_RW_PHYS;
+               sys->io_offset = 0x400;
+               ret = pci_nanoengine_setup_resources(sys->resource);
+               /* Enable alternate memory bus master mode, see
+                * "Intel StrongARM SA1110 Developer's Manual",
+                * section 10.8, "Alternate Memory Bus Master Mode". */
+               GPDR = (GPDR & ~GPIO_MBREQ) | GPIO_MBGNT;
+               GAFR |= GPIO_MBGNT | GPIO_MBREQ;
+               TUCR |= TUCR_MBGPIO;
+       }
+
+       return ret;
+}
+
+static struct hw_pci nanoengine_pci __initdata = {
+       .map_irq                = pci_nanoengine_map_irq,
+       .nr_controllers         = 1,
+       .scan                   = pci_nanoengine_scan_bus,
+       .setup                  = pci_nanoengine_setup,
+};
+
+static int __init nanoengine_pci_init(void)
+{
+       if (machine_is_nanoengine())
+               pci_common_init(&nanoengine_pci);
+       return 0;
+}
+
+subsys_initcall(nanoengine_pci_init);
index 27692d0ffbe81c9d2a5e6931bc323f107973c7c6..cfb76077bd25a19e35e2b1a98134c8896b4b4c74 100644 (file)
@@ -166,9 +166,6 @@ static void __init simpad_map_io(void)
        PCFR = 0;
        PSDR = 0;
 
-       sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
-                             ARRAY_SIZE(simpad_flash_resources));
-       sa11x0_register_mcp(&simpad_mcp_data);
 }
 
 static void simpad_power_off(void)
@@ -216,6 +213,10 @@ static int __init simpad_init(void)
 
        pm_power_off = simpad_power_off;
 
+       sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources,
+                             ARRAY_SIZE(simpad_flash_resources));
+       sa11x0_register_mcp(&simpad_mcp_data);
+
        ret = platform_add_devices(devices, ARRAY_SIZE(devices));
        if(ret)
                printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device");
index 74b6e0e570b64e247681d052da44f6dcb645e16b..ae4f3d80416f2a3c617daabb94fbed14ffd27b9f 100644 (file)
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/sched.h>       /* just for sched_clock() - funny that */
 #include <linux/timex.h>
 #include <linux/clockchips.h>
 
 #include <asm/mach/time.h>
+#include <asm/sched_clock.h>
 #include <mach/hardware.h>
 
+/*
+ * This is the SA11x0 sched_clock implementation.
+ */
+static DEFINE_CLOCK_DATA(cd);
+
+/*
+ * Constants generated by clocks_calc_mult_shift(m, s, 3.6864MHz,
+ * NSEC_PER_SEC, 60).
+ * This gives a resolution of about 271ns and a wrap period of about 19min.
+ */
+#define SC_MULT                2275555556u
+#define SC_SHIFT       23
+
+unsigned long long notrace sched_clock(void)
+{
+       u32 cyc = OSCR;
+       return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
+}
+
+static void notrace sa1100_update_sched_clock(void)
+{
+       u32 cyc = OSCR;
+       update_sched_clock(&cd, cyc, (u32)~0);
+}
+
 #define MIN_OSCR_DELTA 2
 
 static irqreturn_t sa1100_ost0_interrupt(int irq, void *dev_id)
@@ -81,7 +108,6 @@ static struct clocksource cksrc_sa1100_oscr = {
        .rating         = 200,
        .read           = sa1100_read_oscr,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -97,6 +123,9 @@ static void __init sa1100_timer_init(void)
        OIER = 0;               /* disable any timer interrupts */
        OSSR = 0xf;             /* clear status on all timers */
 
+       init_fixed_sched_clock(&cd, sa1100_update_sched_clock, 32,
+                              3686400, SC_MULT, SC_SHIFT);
+
        ckevt_sa1100_osmr0.mult =
                div_sc(3686400, NSEC_PER_SEC, ckevt_sa1100_osmr0.shift);
        ckevt_sa1100_osmr0.max_delta_ns =
@@ -105,12 +134,9 @@ static void __init sa1100_timer_init(void)
                clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_sa1100_osmr0) + 1;
        ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
 
-       cksrc_sa1100_oscr.mult =
-               clocksource_hz2mult(CLOCK_TICK_RATE, cksrc_sa1100_oscr.shift);
-
        setup_irq(IRQ_OST0, &sa1100_timer_irq);
 
-       clocksource_register(&cksrc_sa1100_oscr);
+       clocksource_register_hz(&cksrc_sa1100_oscr, CLOCK_TICK_RATE);
        clockevents_register_device(&ckevt_sa1100_osmr0);
 }
 
index 51dcd59eda6a1aeb965d02b5b94bf66e8737e2ff..6329333572427ec97d1c168aeca2e76c896f965c 100644 (file)
@@ -6,7 +6,7 @@ config ARCH_SH7367
        bool "SH-Mobile G3 (SH7367)"
        select CPU_V6
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select SH_CLK_CPG
        select GENERIC_CLOCKEVENTS
 
@@ -14,7 +14,7 @@ config ARCH_SH7377
        bool "SH-Mobile G4 (SH7377)"
        select CPU_V7
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select SH_CLK_CPG
        select GENERIC_CLOCKEVENTS
 
@@ -22,7 +22,7 @@ config ARCH_SH7372
        bool "SH-Mobile AP4 (SH7372)"
        select CPU_V7
        select HAVE_CLK
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        select SH_CLK_CPG
        select GENERIC_CLOCKEVENTS
 
index d440e5f456ad943979f7e5ec432cee56d91d8c77..ac429ff2c20d85d35172769b18e55b5609e9203f 100644 (file)
@@ -61,6 +61,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <asm/setup.h>
 
 /*
  * Address     Interface               BusWidth        note
index 9f78729098f2721bdd3b46c866ea6fed1a7e08e0..6b186aefcbd63792e22167e47fda0d02a9d9fcef 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7367 registers */
 #define RTFRQCR    0xe6150000
index 3aa026069435a7b99ae1cbff5ccac101af016731..d98deb497c2fac81991411b9ff949c4dfb0afb15 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7372 registers */
 #define FRQCRA         0xe6150000
index f91395aeb9abadd50b13c037670d23260e841920..95942466e63f212fb89c8d7392c15b7507afcb34 100644 (file)
@@ -20,8 +20,8 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/sh_clk.h>
+#include <linux/clkdev.h>
 #include <mach/common.h>
-#include <asm/clkdev.h>
 
 /* SH7377 registers */
 #define RTFRQCR    0xe6150000
index a285d13c74165a2e73a3941a7d1d47d03b91b8ac..f428c4db2b60e60f2c21761859aaec3e4401eea3 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2010 Magnus Damm
  * Copyright (C) 2008 Renesas Solutions Corp.
  *
  * This program is free software; you can redistribute it and/or modify
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
-#include <mach/hardware.h>
 #include <mach/irqs.h>
 
+#define INTCA_BASE     0xe6980000
+#define INTFLGA_OFFS   0x00000018 /* accept pending interrupt */
+#define INTEVTA_OFFS   0x00000020 /* vector number of accepted interrupt */
+#define INTLVLA_OFFS   0x00000030 /* priority level of accepted interrupt */
+#define INTLVLB_OFFS   0x00000034 /* previous priority level */
+
        .macro  disable_fiq
        .endm
 
        .macro  get_irqnr_preamble, base, tmp
-       ldr     \base, =INTFLGA
+       ldr     \base, =INTCA_BASE
        .endm
 
        .macro  arch_ret_to_user, tmp1, tmp2
        .endm
 
        .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \irqnr, [\base]
+       /* The single INTFLGA read access below results in the following:
+        *
+        * 1. INTLVLB is updated with old priority value from INTLVLA
+        * 2. Highest priority interrupt is accepted
+        * 3. INTLVLA is updated to contain priority of accepted interrupt
+        * 4. Accepted interrupt vector is stored in INTFLGA and INTEVTA
+        */
+       ldr     \irqnr, [\base, #INTFLGA_OFFS]
+
+       /* Restore INTLVLA with the value saved in INTLVLB.
+        * This is required to support interrupt priorities properly.
+        */
+       ldrb    \tmp, [\base, #INTLVLB_OFFS]
+       strb    \tmp, [\base, #INTLVLA_OFFS]
+
+       /* Handle invalid vector number case */
        cmp     \irqnr, #0
        beq     1000f
-       /* intevt to irq number */
+
+       /* Convert vector to irq number, same as the evt2irq() macro */
        lsr     \irqnr, \irqnr, #0x5
        subs    \irqnr, \irqnr, #16
 
diff --git a/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt b/arch/arm/mach-shmobile/include/mach/head-ap4evb.txt
new file mode 100644 (file)
index 0000000..e3ebfa7
--- /dev/null
@@ -0,0 +1,87 @@
+LIST "partner-jet-setup.txt"
+LIST "(C) Copyright 2010 Renesas Solutions Corp"
+LIST "Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"
+
+LIST "RWT Setting"
+EW 0xE6020004, 0xA500
+EW 0xE6030004, 0xA500
+
+DD 0x01001000, 0x01001000
+
+LIST "GPIO Setting"
+EB 0xE6051013, 0xA2
+
+LIST "CPG"
+ED 0xE6150080, 0x00000180
+ED 0xE61500C0, 0x00000002
+
+WAIT 1, 0xFE40009C
+
+LIST "FRQCR"
+ED 0xE6150000, 0x2D1305C3
+ED 0xE61500E0, 0x9E40358E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE61500E4, 0x00002000
+
+WAIT 1, 0xFE40009C
+
+LIST "PLL"
+ED 0xE6150028, 0x00004000
+
+WAIT 1, 0xFE40009C
+
+ED 0xE615002C, 0x93000040
+
+WAIT 1, 0xFE40009C
+
+LIST "BSC"
+ED 0xFEC10000, 0x00E0001B
+
+LIST "SBSC1"
+ED 0xFE400354, 0x01AD8000
+ED 0xFE400354, 0x01AD8001
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400008, 0xBCC90151
+ED 0xFE400040, 0x41774113
+ED 0xFE400044, 0x2712E229
+ED 0xFE400048, 0x20C18505
+ED 0xFE40004C, 0x00110209
+ED 0xFE400010, 0x00000087
+
+WAIT 10, 0xFE40009C
+
+ED 0xFE400084, 0x0000003F
+EB 0xFE500000, 0x00
+
+WAIT 5, 0xFE40009C
+
+ED 0xFE400084, 0x0000FF0A
+EB 0xFE500000, 0x00
+
+WAIT 1, 0xFE40009C
+
+ED 0xFE400084, 0x00002201
+EB 0xFE500000, 0x00
+ED 0xFE400084, 0x00000302
+EB 0xFE500000, 0x00
+EB 0xFE5C0000, 0x00
+ED 0xFE400008, 0xBCC90159
+ED 0xFE40008C, 0x88800004
+ED 0xFE400094, 0x00000004
+ED 0xFE400028, 0xA55A0032
+ED 0xFE40002C, 0xA55A000C
+ED 0xFE400020, 0xA55A2048
+ED 0xFE400008, 0xBCC90959
+
+LIST "Change CPGA setting"
+ED 0xE61500E0, 0x9E40352E
+ED 0xE6150004, 0x80331050
+
+WAIT 1, 0xFE40009C
+
+ED 0xE6150354, 0x00000002
index 4aecf6e3a859f801111fafa328a44b3d0de3b311..2b8fd8b942feca160e61fe513d8856ffcb0d83a7 100644 (file)
@@ -2,6 +2,6 @@
 #define __ASM_MACH_VMALLOC_H
 
 /* Vmalloc at ... - 0xe5ffffff */
-#define VMALLOC_END 0xe6000000
+#define VMALLOC_END 0xe6000000UL
 
 #endif /* __ASM_MACH_VMALLOC_H */
diff --git a/arch/arm/mach-shmobile/include/mach/zboot.h b/arch/arm/mach-shmobile/include/mach/zboot.h
new file mode 100644 (file)
index 0000000..3ad86b7
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef ZBOOT_H
+#define ZBOOT_H
+
+#include <asm/mach-types.h>
+#include <mach/zboot_macros.h>
+
+/**************************************************
+ *
+ *             board specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_MACH_AP4EVB
+#define MACH_TYPE      MACH_TYPE_AP4EVB
+#include "mach/head-ap4evb.txt"
+#else
+#error "unsupported board."
+#endif
+
+#endif /* ZBOOT_H */
diff --git a/arch/arm/mach-shmobile/include/mach/zboot_macros.h b/arch/arm/mach-shmobile/include/mach/zboot_macros.h
new file mode 100644 (file)
index 0000000..aa6111f
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __ZBOOT_MACRO_H
+#define __ZBOOT_MACRO_H
+
+/* The LIST command is used to include comments in the script */
+.macro LIST comment
+.endm
+
+/* The ED command is used to write a 32-bit word */
+.macro ED, addr, data
+       LDR     r0, 1f
+       LDR     r1, 2f
+       STR     r1, [r0]
+       B       3f
+1 :    .long   \addr
+2 :    .long   \data
+3 :
+.endm
+
+/* The EW command is used to write a 16-bit word */
+.macro EW, addr, data
+       LDR     r0, 1f
+       LDR     r1, 2f
+       STRH    r1, [r0]
+       B       3f
+1 :    .long   \addr
+2 :    .long   \data
+3 :
+.endm
+
+/* The EB command is used to write an 8-bit word */
+.macro EB, addr, data
+       LDR     r0, 1f
+       LDR     r1, 2f
+       STRB    r1, [r0]
+       B       3f
+1 :    .long   \addr
+2 :    .long   \data
+3 :
+.endm
+
+/* The WAIT command is used to delay the execution */
+.macro  WAIT, time, reg
+       LDR     r1, 1f
+       LDR     r0, 2f
+       STR     r0, [r1]
+10 :
+       LDR     r0, [r1]
+       CMP     r0, #0x00000000
+       BNE     10b
+       NOP
+       B       3f
+1 :    .long   \reg
+2 :    .long   \time * 100
+3 :
+.endm
+
+/* The DD command is used to read a 32-bit word */
+.macro  DD, start, end
+       LDR     r1, 1f
+       B       2f
+1 :    .long   \start
+2 :
+.endm
+
+#endif /* __ZBOOT_MACRO_H */
index ba32a15127ab7afdd7fe53354dafd902c2939fca..3970a9cdce26e3d3afc39c1d7630639238744769 100644 (file)
@@ -12,8 +12,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/clock.h>
 #include <mach/irqs.h>
index 78d06008841d87adda56524b0b101555097ce55d..e0a8d609afe1d1a6d66c97ac4c882468961465f4 100644 (file)
@@ -35,7 +35,6 @@ static struct clocksource clocksource_tcc = {
        .rating         = 200,
        .read           = tcc_get_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 28,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -103,9 +102,7 @@ static int __init tcc_clockevent_init(struct clk *clock)
 {
        unsigned int c = clk_get_rate(clock);
 
-       clocksource_tcc.mult = clocksource_hz2mult(c,
-                                       clocksource_tcc.shift);
-       clocksource_register(&clocksource_tcc);
+       clocksource_register_hz(&clocksource_tcc, c);
 
        clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC,
                                        clockevent_tcc.shift);
index ae19f95585be119c51456a9d2d75183fc3b1ff4c..77948e0f49098e5decc0858257e26a0e30537d59 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/slab.h>
 #include <linux/seq_file.h>
 #include <linux/regulator/consumer.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include "clock.h"
 #include "board.h"
index 94fd859770f1a992a0bd001e265a781c3bf7448b..083a4cfc6cf0d0ef635a74950a5557415e31e9b1 100644 (file)
@@ -21,7 +21,7 @@
 #define __MACH_TEGRA_CLOCK_H
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #define DIV_BUS                        (1 << 0)
 #define DIV_U71                        (1 << 1)
index 8e7f115aa21e8b33c11c1a889d7aa2634445bd84..a5cb1ce76ff2a5be2a43fe398bb64f37423d4acd 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void cpu_enter_lowpower(void)
 {
        unsigned int v;
@@ -29,13 +26,13 @@ static inline void cpu_enter_lowpower(void)
         * Turn off coherency
         */
        "       mrc     p15, 0, %0, c1, c0, 1\n"
-       "       bic     %0, %0, #0x20\n"
+       "       bic     %0, %0, %2\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
        "       mrc     p15, 0, %0, c1, c0, 0\n"
        "       bic     %0, %0, #0x04\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
          : "=&r" (v)
-         : "r" (0)
+         : "r" (0), "Ir" (CR_C)
          : "cc");
 }
 
@@ -45,17 +42,17 @@ static inline void cpu_leave_lowpower(void)
 
        asm volatile(
        "mrc    p15, 0, %0, c1, c0, 0\n"
-       "       orr     %0, %0, #0x04\n"
+       "       orr     %0, %0, %1\n"
        "       mcr     p15, 0, %0, c1, c0, 0\n"
        "       mrc     p15, 0, %0, c1, c0, 1\n"
        "       orr     %0, %0, #0x20\n"
        "       mcr     p15, 0, %0, c1, c0, 1\n"
          : "=&r" (v)
-         :
+         : "Ir" (CR_C)
          : "cc");
 }
 
-static inline void platform_do_lowpower(unsigned int cpu)
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
 {
        /*
         * there is no power-control hardware on this platform, so all
@@ -79,22 +76,19 @@ static inline void platform_do_lowpower(unsigned int cpu)
                /*}*/
 
                /*
-                * getting here, means that we have come out of WFI without
+                * Getting here, means that we have come out of WFI without
                 * having been woken up - this shouldn't happen
                 *
-                * The trouble is, letting people know about this is not really
-                * possible, since we are currently running incoherently, and
-                * therefore cannot safely call printk() or anything else
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
                 */
-#ifdef DEBUG
-               printk(KERN_WARN "CPU%u: spurious wakeup call\n", cpu);
-#endif
+               (*spurious)++;
        }
 }
 
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -104,30 +98,22 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-#endif
-
-       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
+       int spurious = 0;
 
        /*
         * we're ready for shutdown now, so do it
         */
        cpu_enter_lowpower();
-       platform_do_lowpower(cpu);
+       platform_do_lowpower(cpu, &spurious);
 
        /*
         * bring this CPU back into the world of cache
         * coherency, and then restore interrupts
         */
        cpu_leave_lowpower();
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
 }
 
 int platform_cpu_disable(unsigned int cpu)
index 2ba9e5c9d2f6f711aecae8bda9506c7008d406a0..dd165c53889de61d499731f8e5b6da8fc88d5d55 100644 (file)
@@ -16,8 +16,8 @@
 #include <mach/io.h>
 
 #if defined(CONFIG_ARM_GIC)
-
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
        /* Uses the GIC interrupt controller built into the cpu */
 #define ICTRL_BASE (IO_CPU_VIRT + 0x100)
 
        .macro  arch_ret_to_user, tmp1, tmp2
        .endm
-
-       /*
-        * The interrupt numbering scheme is defined in the
-        * interrupt controller spec.  To wit:
-        *
-        * Interrupts 0-15 are IPI
-        * 16-28 are reserved
-        * 29-31 are local.  We allow 30 to be used for the watchdog.
-        * 32-1020 are global
-        * 1021-1022 are reserved
-        * 1023 is "spurious" (no interrupt)
-        *
-        * For now, we ignore all local interrupts so only return an interrupt
-        * if it's between 30 and 1020.  The test_for_ipi routine below will
-        * pick up on IPIs.
-        *
-        * A simple read from the controller will tell us the number of the
-        * highest priority enabled interrupt.  We then just need to check
-        * whether it is in the valid range for an IRQ (30-1020 inclusive).
-        */
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-       /* bits 12-10 = src CPU, 9-0 = int # */
-       ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-       ldr             \tmp, =1021
-
-       bic     \irqnr, \irqstat, #0x1c00
-
-       cmp     \irqnr, #29
-       cmpcc   \irqnr, \irqnr
-       cmpne   \irqnr, \tmp
-       cmpcs   \irqnr, \irqnr
-
-       .endm
-
-       /* We assume that irqstat (the raw value of the IRQ acknowledge
-        * register) is preserved from the macro above.
-        * If there is an IPI, we immediately signal end of interrupt on the
-        * controller, since this requires the original irqstat value which
-        * we won't easily be able to recreate later.
-        */
-
-       .macro test_for_ipi, irqnr, irqstat, base, tmp
-       bic     \irqnr, \irqstat, #0x1c00
-       cmp     \irqnr, #16
-       strcc   \irqstat, [\base, #GIC_CPU_EOI]
-       cmpcs   \irqnr, \irqnr
-       .endm
-
-       /* As above, this assumes that irqstat and base are preserved.. */
-
-       .macro test_for_ltirq, irqnr, irqstat, base, tmp
-       bic     \irqnr, \irqstat, #0x1c00
-       mov     \tmp, #0
-       cmp     \irqnr, #29
-       moveq   \tmp, #1
-       streq   \irqstat, [\base, #GIC_CPU_EOI]
-       cmp     \tmp, #0
-       .endm
-
 #else
        /* legacy interrupt controller for AP16 */
        .macro  disable_fiq
index f0981b1ac59eea58d65a1bbd251ad660deb80a0f..4cea2230c8dc92a41fb351b41d613e76fa0811ff 100644 (file)
@@ -65,8 +65,8 @@
 
 #ifndef __ASSEMBLER__
 
-#define __arch_ioremap(p, s, t)        tegra_ioremap(p, s, t)
-#define __arch_iounmap(v)      tegra_iounmap(v)
+#define __arch_ioremap         tegra_ioremap
+#define __arch_iounmap         tegra_iounmap
 
 void __iomem *tegra_ioremap(unsigned long phys, size_t size, unsigned int type);
 void tegra_iounmap(volatile void __iomem *addr);
index e4a34a35a54466a1aecc7b3ea0ffe67c9dcee3df..c8221b38ee7c32ec2e53d5a24fe6c0a90e6c3743 100644 (file)
@@ -2,21 +2,13 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
-{
-       gic_raise_softirq(mask, 1);
-}
-
-/*
- * Do nothing on MPcore.
- */
-static inline void smp_cross_call_done(cpumask_t callmap)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 50a8dfb9a0cfe8cbb1dbdaeb8a913d5858000902..5407de01abf0a6eccf51764d4c8d40d319132992 100644 (file)
@@ -94,8 +94,8 @@ void __init tegra_init_irq(void)
                writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
        }
 
-       gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
-       gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
+       gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
+                IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
 
        gic = get_irq_chip(29);
        gic_unmask_irq = gic->unmask;
index 1c0fd92cab39e44779a3823e89d5248997163a72..ec1f68924edf354127c1466b25587cb078197460 100644 (file)
@@ -22,7 +22,6 @@
 #include <asm/cacheflush.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 
 #include <mach/iomap.h>
@@ -41,14 +40,12 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x100);
+       gic_secondary_init(0);
 
        /*
         * Synchronise with the boot thread.
@@ -117,24 +114,20 @@ void __init smp_init_cpus(void)
 {
        unsigned int i, ncores = scu_get_core_count(scu_base);
 
+       if (ncores > NR_CPUS) {
+               printk(KERN_ERR "Tegra: no. of cores (%u) greater than configured (%u), clipping\n",
+                       ncores, NR_CPUS);
+               ncores = NR_CPUS;
+       }
+
        for (i = 0; i < ncores; i++)
                cpu_set(i, cpu_possible_map);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned int ncores = scu_get_core_count(scu_base);
-       unsigned int cpu = smp_processor_id();
        int i;
 
-       smp_store_cpu_info(cpu);
-
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
-
        /*
         * Initialise the present map, which describes the set of CPUs
         * actually populated at the present time.
@@ -142,15 +135,5 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
-       /*
-        * Initialise the SCU if there are more than one CPU and let
-        * them know where to start. Note that, on modern versions of
-        * MILO, the "poke" doesn't actually do anything until each
-        * individual core is sent a soft interrupt to get it out of
-        * WFI
-        */
-       if (max_cpus > 1) {
-               percpu_timer_setup();
-               scu_enable(scu_base);
-       }
+       scu_enable(scu_base);
 }
index ae3b308e22a4d158b464d8b47f383a7509cf6efd..f0dae6d8ba520a5046848dc7710caa92624a4f0d 100644 (file)
@@ -24,8 +24,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/hrtimer.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <mach/iomap.h>
 
index 9057d6fd1d31d441dcc99c234c2d838c91e65a72..7b8ad1f98f447c5a6f5694d53388b9502ed972d2 100644 (file)
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/clocksource.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <linux/cnt32_to_63.h>
 
 #include <asm/mach/time.h>
 #include <asm/localtimer.h>
+#include <asm/sched_clock.h>
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
@@ -91,7 +92,7 @@ static void tegra_timer_set_mode(enum clock_event_mode mode,
 
 static cycle_t tegra_clocksource_read(struct clocksource *cs)
 {
-       return cnt32_to_63(timer_readl(TIMERUS_CNTR_1US));
+       return timer_readl(TIMERUS_CNTR_1US);
 }
 
 static struct clock_event_device tegra_clockevent = {
@@ -106,14 +107,29 @@ static struct clocksource tegra_clocksource = {
        .name   = "timer_us",
        .rating = 300,
        .read   = tegra_clocksource_read,
-       .mask   = 0x7FFFFFFFFFFFFFFFULL,
+       .mask   = CLOCKSOURCE_MASK(32),
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
-unsigned long long sched_clock(void)
+static DEFINE_CLOCK_DATA(cd);
+
+/*
+ * Constants generated by clocks_calc_mult_shift(m, s, 1MHz, NSEC_PER_SEC, 60).
+ * This gives a resolution of about 1us and a wrap period of about 1h11min.
+ */
+#define SC_MULT                4194304000u
+#define SC_SHIFT       22
+
+unsigned long long notrace sched_clock(void)
 {
-       return clocksource_cyc2ns(tegra_clocksource.read(&tegra_clocksource),
-               tegra_clocksource.mult, tegra_clocksource.shift);
+       u32 cyc = timer_readl(TIMERUS_CNTR_1US);
+       return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
+}
+
+static void notrace tegra_update_sched_clock(void)
+{
+       u32 cyc = timer_readl(TIMERUS_CNTR_1US);
+       update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
@@ -158,6 +174,9 @@ static void __init tegra_init_timer(void)
                WARN(1, "Unknown clock rate");
        }
 
+       init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32,
+                              1000000, SC_MULT, SC_SHIFT);
+
        if (clocksource_register_hz(&tegra_clocksource, 1000000)) {
                printk(KERN_ERR "Failed to register clocksource\n");
                BUG();
index 7458fc6df5c67b466184bc6a4a317745304101ee..fabcc49abe80c7e63bbec3cedc275d60ad6c4728 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/timer.h>
 #include <linux/io.h>
 #include <linux/seq_file.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/syscon.h>
 
index 3fc4472719be0f05bfeb3823fbe000a7818cf2d5..3ec58bd2d6e47a38c8ff2e06e289e6f2682b9490 100644 (file)
@@ -9,6 +9,7 @@
  * Author: Linus Walleij <linus.walleij@stericsson.com>
  */
 #include <linux/interrupt.h>
+#include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/timex.h>
 #include <linux/clockchips.h>
@@ -21,6 +22,7 @@
 #include <mach/hardware.h>
 
 /* Generic stuff */
+#include <asm/sched_clock.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
@@ -352,12 +354,18 @@ static struct clocksource clocksource_u300_1mhz = {
  * this wraps around for now, since it is just a relative time
  * stamp. (Inspired by OMAP implementation.)
  */
+static DEFINE_CLOCK_DATA(cd);
+
 unsigned long long notrace sched_clock(void)
 {
-       return clocksource_cyc2ns(clocksource_u300_1mhz.read(
-                                 &clocksource_u300_1mhz),
-                                 clocksource_u300_1mhz.mult,
-                                 clocksource_u300_1mhz.shift);
+       u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
+       return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace u300_update_sched_clock(void)
+{
+       u32 cyc = readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
+       update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 
@@ -375,6 +383,8 @@ static void __init u300_timer_init(void)
        clk_enable(clk);
        rate = clk_get_rate(clk);
 
+       init_sched_clock(&cd, u300_update_sched_clock, 32, rate);
+
        /*
         * Disable the "OS" and "DD" timers - these are designed for Symbian!
         * Example usage in cnh1601578 cpu subsystem pd_timer_app.c
@@ -412,9 +422,7 @@ static void __init u300_timer_init(void)
        writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
                U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2);
 
-       clocksource_calc_mult_shift(&clocksource_u300_1mhz,
-                                   rate, APPTIMER_MIN_RANGE);
-       if (clocksource_register(&clocksource_u300_1mhz))
+       if (clocksource_register_hz(&clocksource_u300_1mhz, rate))
                printk(KERN_ERR "timer: failed to initialize clock "
                       "source %s\n", clocksource_u300_1mhz.name);
 
index 912d1cc18c5767affee605e444becf3f07775c4b..ccff2dae167f64a9c37eaca4f117137fa31483d7 100644 (file)
@@ -13,8 +13,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 #include <plat/mtu.h>
 #include <mach/hardware.h>
index a3700bc374d379c6e4fbfc57aef7d5c8b92c0803..5730409c0f7ddbaef45410c852517e8af113272b 100644 (file)
@@ -52,8 +52,8 @@ void __init ux500_map_io(void)
 
 void __init ux500_init_irq(void)
 {
-       gic_dist_init(0, __io_address(UX500_GIC_DIST_BASE), 29);
-       gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+       gic_init(0, 29, __io_address(UX500_GIC_DIST_BASE),
+                __io_address(UX500_GIC_CPU_BASE));
 
        /*
         * Init clocks here so that they are available for system timer
index a6be2cdf2b2f49a0302cac06cb5df95c08baf054..64fa451edcfd486bdbaa0163f55e93399597d8ed 100644 (file)
@@ -23,7 +23,6 @@ ENTRY(u8500_secondary_startup)
        ldmia   r4, {r5, r6}
        sub     r4, r4, r5
        add     r6, r6, r4
-       dsb
 pen:   ldr     r7, [r6]
        cmp     r7, r0
        bne     pen
index b782a03024be18b3c82ca32986bb54a432717f20..dd8037ebccf8b427e1b9fefa738a133f39082ef0 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
-#include <linux/completion.h>
 
 #include <asm/cacheflush.h>
 
 extern volatile int pen_release;
 
-static DECLARE_COMPLETION(cpu_killed);
-
 static inline void platform_do_lowpower(unsigned int cpu)
 {
        flush_cache_all();
@@ -38,7 +35,7 @@ static inline void platform_do_lowpower(unsigned int cpu)
 
 int platform_cpu_kill(unsigned int cpu)
 {
-       return wait_for_completion_timeout(&cpu_killed, 5000);
+       return 1;
 }
 
 /*
@@ -48,19 +45,6 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void platform_cpu_die(unsigned int cpu)
 {
-#ifdef DEBUG
-       unsigned int this_cpu = hard_smp_processor_id();
-
-       if (cpu != this_cpu) {
-               printk(KERN_CRIT "Eek! platform_cpu_die running on %u, should be %u\n",
-                          this_cpu, cpu);
-               BUG();
-       }
-#endif
-
-       printk(KERN_NOTICE "CPU%u: shutdown\n", cpu);
-       complete(&cpu_killed);
-
        /* directly enter low power state, skipping secure registers */
        platform_do_lowpower(cpu);
 }
index 60ea88db8283a521db2fe1e7396d171bff76db6c..a37f585a3ecbbca21270c78a13681c1955f06c4c 100644 (file)
@@ -11,7 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
+#define HAVE_GET_IRQNR_PREAMBLE
+#include <asm/hardware/entry-macro-gic.S>
 
                .macro  disable_fiq
                .endm
 
                .macro  arch_ret_to_user, tmp1, tmp2
                .endm
-
-               /*
-                * The interrupt numbering scheme is defined in the
-                * interrupt controller spec.  To wit:
-                *
-                * Interrupts 0-15 are IPI
-                * 16-28 are reserved
-                * 29-31 are local.  We allow 30 to be used for the watchdog.
-                * 32-1020 are global
-                * 1021-1022 are reserved
-                * 1023 is "spurious" (no interrupt)
-                *
-                * For now, we ignore all local interrupts so only return an
-                * interrupt if it's between 30 and 1020. The test_for_ipi
-                * routine below will pick up on IPIs.
-                *
-                * A simple read from the controller will tell us the number
-                * of the highest priority enabled interrupt. We then just
-                * need to check whether it is in the valid range for an
-                * IRQ (30-1020 inclusive).
-                */
-
-               .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-               /* bits 12-10 = src CPU, 9-0 = int # */
-               ldr     \irqstat, [\base, #GIC_CPU_INTACK]
-
-               ldr     \tmp, =1021
-
-               bic     \irqnr, \irqstat, #0x1c00
-
-               cmp     \irqnr, #29
-               cmpcc   \irqnr, \irqnr
-               cmpne   \irqnr, \tmp
-               cmpcs   \irqnr, \irqnr
-
-               .endm
-
-               /* We assume that irqstat (the raw value of the IRQ
-                * acknowledge register) is preserved from the macro above.
-                * If there is an IPI, we immediately signal end of
-                * interrupt on the controller, since this requires the
-                * original irqstat value which we won't easily be able
-                * to recreate later.
-                */
-
-               .macro test_for_ipi, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               cmp     \irqnr, #16
-               strcc   \irqstat, [\base, #GIC_CPU_EOI]
-               cmpcs   \irqnr, \irqnr
-               .endm
-
-               /* As above, this assumes that irqstat and base
-                * are preserved..
-                */
-
-               .macro test_for_ltirq, irqnr, irqstat, base, tmp
-               bic     \irqnr, \irqstat, #0x1c00
-               mov     \tmp, #0
-               cmp     \irqnr, #29
-               moveq   \tmp, #1
-               streq   \irqstat, [\base, #GIC_CPU_EOI]
-               cmp     \tmp, #0
-               .endm
index 197e8417375e17f38942e443a963a686cb90905b..ca2b15b1b3b18d63ba734daed49fe5c1ea99c7a6 100644 (file)
@@ -10,7 +10,6 @@
 #define ASMARM_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /* This is required to wakeup the secondary core */
 extern void u8500_secondary_startup(void);
@@ -18,8 +17,8 @@ extern void u8500_secondary_startup(void);
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 #endif
index ade2e17f253c3665767d26d66c703ad9d1485bc1..d77e76cb7edd2eb107e74eb9200b39bcda5a6b39 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
 
  */
 volatile int pen_release = -1;
 
-static unsigned int __init get_core_count(void)
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
 {
-       return scu_get_core_count(__io_address(UX500_SCU_BASE));
+       pen_release = val;
+       smp_wmb();
+       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
 }
 
 static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_cpu_init(0, __io_address(UX500_GIC_CPU_BASE));
+       gic_secondary_init(0);
 
        /*
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
-       pen_release = -1;
+       write_pen_release(-1);
 
        /*
         * Synchronise with the boot thread.
@@ -74,11 +79,9 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * the holding pen - release it, then wait for it to flag
         * that it has been released by resetting pen_release.
         */
-       pen_release = cpu;
-       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-       outer_clean_range(__pa(&pen_release), __pa(&pen_release) + 1);
+       write_pen_release(cpu);
 
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
@@ -97,9 +100,6 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init wakeup_secondary(void)
 {
-       /* nobody is to be released from the pen yet */
-       pen_release = -1;
-
        /*
         * write the address of secondary startup into the backup ram register
         * at offset 0x1FF4, then write the magic number 0xA1FEED01 to the
@@ -126,40 +126,26 @@ static void __init wakeup_secondary(void)
  */
 void __init smp_init_cpus(void)
 {
-       unsigned int i, ncores = get_core_count();
+       unsigned int i, ncores;
 
-       for (i = 0; i < ncores; i++)
-               set_cpu_possible(i, true);
-}
-
-void __init smp_prepare_cpus(unsigned int max_cpus)
-{
-       unsigned int ncores = get_core_count();
-       unsigned int cpu = smp_processor_id();
-       int i;
+       ncores = scu_get_core_count(__io_address(UX500_SCU_BASE));
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "U8500: strange CM count of 0? Default to 1\n");
-               ncores = 1;
-       }
-
-       if (ncores > num_possible_cpus())       {
+       if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "U8500: no. of cores (%d) greater than configured "
                       "maximum of %d - clipping\n",
-                      ncores, num_possible_cpus());
-               ncores = num_possible_cpus();
+                      ncores, NR_CPUS);
+               ncores = NR_CPUS;
        }
 
-       smp_store_cpu_info(cpu);
+       for (i = 0; i < ncores; i++)
+               set_cpu_possible(i, true);
+}
 
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+       int i;
 
        /*
         * Initialise the present map, which describes the set of CPUs
@@ -168,13 +154,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-               scu_enable(__io_address(UX500_SCU_BASE));
-               wakeup_secondary();
-       }
+       scu_enable(__io_address(UX500_SCU_BASE));
+       wakeup_secondary();
 }
index c781f30c8368a0d9dc4f33f271f91121f08c29fc..3f7b5e9d83c51633556dca30b9fada357c49e0ba 100644 (file)
@@ -4,6 +4,7 @@ menu "Versatile platform type"
 config ARCH_VERSATILE_PB
        bool "Support Versatile/PB platform"
        select CPU_ARM926T
+       select MIGHT_HAVE_PCI
        default y
        help
          Include support for the ARM(R) Versatile/PB platform.
index e38acb0f89c884b961bdb1dc11fa59b1a0112bc0..13a83e45a33b03b79aa138af7b3b7ffa3d6a4786 100644 (file)
@@ -31,8 +31,8 @@
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/leds.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
-#include <mach/clkdev.h>
 #include <mach/hardware.h>
 #include <mach/platform.h>
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
+
+#include <plat/sched_clock.h>
 
 #include "core.h"
 
@@ -885,6 +886,12 @@ void __init versatile_init(void)
 #endif
 }
 
+/*
+ * The sched_clock counter
+ */
+#define REFCOUNTER             (__io_address(VERSATILE_SYS_BASE) + \
+                                VERSATILE_SYS_24MHz_OFFSET)
+
 /*
  * Where is the timer (VA)?
  */
@@ -900,6 +907,8 @@ static void __init versatile_timer_init(void)
 {
        u32 val;
 
+       versatile_sched_clock_init(REFCOUNTER, 24000000);
+
        /* 
         * set clock frequency: 
         *      VERSATILE_REFCLK is 32KHz
index 1b71b77ade2297b1506af506496a0c50bc6ef78d..2c0ac7de28142dfb46ce9e4463c8bea03fff58eb 100644 (file)
@@ -5,4 +5,5 @@
 obj-y                                  := v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)      += ct-ca9x4.o
 obj-$(CONFIG_SMP)                      += platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)              += hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)             += localtimer.o
index 57dd95ce41f90f677f0f5a7de2db2f8ea8be5b7a..362780d868de02f5c5ea0e42c3d80e5b02f09607 100644 (file)
@@ -22,5 +22,3 @@ struct map_desc;
 
 void v2m_map_io(struct map_desc *tile, size_t num);
 extern struct sys_timer v2m_timer;
-
-extern void __iomem *gic_cpu_base_addr;
index fd25ccd7272f7045b24a193f4c025a84c3bca97b..e628402b754cd4c41527d67c87504ad4fea43e8e 100644 (file)
@@ -8,8 +8,8 @@
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/pgtable.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/pmu.h>
 #include <asm/smp_twd.h>
 
-#include <mach/clkdev.h>
 #include <mach/ct-ca9x4.h>
 
-#include <plat/timer-sp.h>
+#include <asm/hardware/timer-sp.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -60,13 +59,10 @@ static void __init ct_ca9x4_map_io(void)
        v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
 }
 
-void __iomem *gic_cpu_base_addr;
-
 static void __init ct_ca9x4_init_irq(void)
 {
-       gic_cpu_base_addr = MMIO_P2V(A9_MPCORE_GIC_CPU);
-       gic_dist_init(0, MMIO_P2V(A9_MPCORE_GIC_DIST), 29);
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_init(0, 29, MMIO_P2V(A9_MPCORE_GIC_DIST),
+                MMIO_P2V(A9_MPCORE_GIC_CPU));
 }
 
 #if 0
diff --git a/arch/arm/mach-vexpress/hotplug.c b/arch/arm/mach-vexpress/hotplug.c
new file mode 100644 (file)
index 0000000..ea4cbfb
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ *  linux/arch/arm/mach-realview/hotplug.c
+ *
+ *  Copyright (C) 2002 ARM Ltd.
+ *  All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+
+extern volatile int pen_release;
+
+static inline void cpu_enter_lowpower(void)
+{
+       unsigned int v;
+
+       flush_cache_all();
+       asm volatile(
+               "mcr    p15, 0, %1, c7, c5, 0\n"
+       "       mcr     p15, 0, %1, c7, c10, 4\n"
+       /*
+        * Turn off coherency
+        */
+       "       mrc     p15, 0, %0, c1, c0, 1\n"
+       "       bic     %0, %0, %3\n"
+       "       mcr     p15, 0, %0, c1, c0, 1\n"
+       "       mrc     p15, 0, %0, c1, c0, 0\n"
+       "       bic     %0, %0, %2\n"
+       "       mcr     p15, 0, %0, c1, c0, 0\n"
+         : "=&r" (v)
+         : "r" (0), "Ir" (CR_C), "Ir" (0x40)
+         : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+       unsigned int v;
+
+       asm volatile(
+               "mrc    p15, 0, %0, c1, c0, 0\n"
+       "       orr     %0, %0, %1\n"
+       "       mcr     p15, 0, %0, c1, c0, 0\n"
+       "       mrc     p15, 0, %0, c1, c0, 1\n"
+       "       orr     %0, %0, %2\n"
+       "       mcr     p15, 0, %0, c1, c0, 1\n"
+         : "=&r" (v)
+         : "Ir" (CR_C), "Ir" (0x40)
+         : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+       /*
+        * there is no power-control hardware on this platform, so all
+        * we can do is put the core into WFI; this is safe as the calling
+        * code will have already disabled interrupts
+        */
+       for (;;) {
+               /*
+                * here's the WFI
+                */
+               asm(".word      0xe320f003\n"
+                   :
+                   :
+                   : "memory", "cc");
+
+               if (pen_release == cpu) {
+                       /*
+                        * OK, proper wakeup, we're done
+                        */
+                       break;
+               }
+
+               /*
+                * Getting here, means that we have come out of WFI without
+                * having been woken up - this shouldn't happen
+                *
+                * Just note it happening - when we're woken, we can report
+                * its occurrence.
+                */
+               (*spurious)++;
+       }
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+       return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+       int spurious = 0;
+
+       /*
+        * we're ready for shutdown now, so do it
+        */
+       cpu_enter_lowpower();
+       platform_do_lowpower(cpu, &spurious);
+
+       /*
+        * bring this CPU back into the world of cache
+        * coherency, and then restore interrupts
+        */
+       cpu_leave_lowpower();
+
+       if (spurious)
+               pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+       /*
+        * we don't allow CPU 0 to be shutdown (it is still too special
+        * e.g. clock tick interrupts)
+        */
+       return cpu == 0 ? -EPERM : 0;
+}
index 20e9fb514f0ac6aa94d4185ae75b6401e7459f96..73c11297509ed4bf9cfdefad92b831aab9495218 100644 (file)
@@ -1,67 +1,7 @@
-#include <asm/hardware/gic.h>
+#include <asm/hardware/entry-macro-gic.S>
 
        .macro  disable_fiq
        .endm
 
-       .macro  get_irqnr_preamble, base, tmp
-       ldr     \base, =gic_cpu_base_addr
-       ldr     \base, [\base]
-       .endm
-
        .macro  arch_ret_to_user, tmp1, tmp2
        .endm
-
-       /*
-        * The interrupt numbering scheme is defined in the
-        * interrupt controller spec.  To wit:
-        *
-        * Interrupts 0-15 are IPI
-        * 16-28 are reserved
-        * 29-31 are local.  We allow 30 to be used for the watchdog.
-        * 32-1020 are global
-        * 1021-1022 are reserved
-        * 1023 is "spurious" (no interrupt)
-        *
-        * For now, we ignore all local interrupts so only return an interrupt if it's
-        * between 30 and 1020.  The test_for_ipi routine below will pick up on IPIs.
-        *
-        * A simple read from the controller will tell us the number of the highest
-        * priority enabled interrupt.  We then just need to check whether it is in the
-        * valid range for an IRQ (30-1020 inclusive).
-        */
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-       ldr     \tmp, =1021
-       bic     \irqnr, \irqstat, #0x1c00
-       cmp     \irqnr, #29
-       cmpcc   \irqnr, \irqnr
-       cmpne   \irqnr, \tmp
-       cmpcs   \irqnr, \irqnr
-       .endm
-
-       /* We assume that irqstat (the raw value of the IRQ acknowledge
-        * register) is preserved from the macro above.
-        * If there is an IPI, we immediately signal end of interrupt on the
-        * controller, since this requires the original irqstat value which
-        * we won't easily be able to recreate later.
-        */
-
-       .macro test_for_ipi, irqnr, irqstat, base, tmp
-       bic     \irqnr, \irqstat, #0x1c00
-       cmp     \irqnr, #16
-       strcc   \irqstat, [\base, #GIC_CPU_EOI]
-       cmpcs   \irqnr, \irqnr
-       .endm
-
-       /* As above, this assumes that irqstat and base are preserved.. */
-
-       .macro test_for_ltirq, irqnr, irqstat, base, tmp
-       bic     \irqnr, \irqstat, #0x1c00
-       mov     \tmp, #0
-       cmp     \irqnr, #29
-       moveq   \tmp, #1
-       streq   \irqstat, [\base, #GIC_CPU_EOI]
-       cmp     \tmp, #0
-       .endm
-
index 5a6da4fd247e86268c660d82ff8c4a4325021ffa..4c05e4a9713a311c0be2ee63912b32b6a21400b5 100644 (file)
@@ -2,13 +2,12 @@
 #define __MACH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /*
  * We use IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 #endif
index 670970699ba93e09d2b270cdc0a061b17b64177b..b1687b6abe63024daa40582b49446aa4eb3965cc 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/io.h>
 
 #include <asm/cacheflush.h>
-#include <asm/localtimer.h>
 #include <asm/smp_scu.h>
 #include <asm/unified.h>
 
@@ -35,6 +34,19 @@ extern void vexpress_secondary_startup(void);
  */
 volatile int __cpuinitdata pen_release = -1;
 
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+       pen_release = val;
+       smp_wmb();
+       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
 static void __iomem *scu_base_addr(void)
 {
        return MMIO_P2V(A9_MPCORE_SCU);
@@ -44,21 +56,18 @@ static DEFINE_SPINLOCK(boot_lock);
 
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
-       trace_hardirqs_off();
-
        /*
         * if any interrupts are already enabled for the primary
         * core (e.g. timer irq), then they will not have been enabled
         * for us: do so
         */
-       gic_cpu_init(0, gic_cpu_base_addr);
+       gic_secondary_init(0);
 
        /*
         * let the primary processor know we're out of the
         * pen, then head off into the C entry point
         */
-       pen_release = -1;
-       smp_wmb();
+       write_pen_release(-1);
 
        /*
         * Synchronise with the boot thread.
@@ -83,16 +92,14 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * since we haven't sent them a soft interrupt, they shouldn't
         * be there.
         */
-       pen_release = cpu;
-       __cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-       outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+       write_pen_release(cpu);
 
        /*
         * Send the secondary CPU a soft interrupt, thereby causing
         * the boot monitor to read the system wide flags register,
         * and branch to the address found there.
         */
-       smp_cross_call(cpumask_of(cpu));
+       smp_cross_call(cpumask_of(cpu), 1);
 
        timeout = jiffies + (1 * HZ);
        while (time_before(jiffies, timeout)) {
@@ -124,13 +131,6 @@ void __init smp_init_cpus(void)
        ncores = scu_base ? scu_get_core_count(scu_base) : 1;
 
        /* sanity check */
-       if (ncores == 0) {
-               printk(KERN_ERR
-                      "vexpress: strange CM count of 0? Default to 1\n");
-
-               ncores = 1;
-       }
-
        if (ncores > NR_CPUS) {
                printk(KERN_WARNING
                       "vexpress: no. of cores (%d) greater than configured "
@@ -143,20 +143,10 @@ void __init smp_init_cpus(void)
                set_cpu_possible(i, true);
 }
 
-void __init smp_prepare_cpus(unsigned int max_cpus)
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-       unsigned int ncores = num_possible_cpus();
-       unsigned int cpu = smp_processor_id();
        int i;
 
-       smp_store_cpu_info(cpu);
-
-       /*
-        * are we trying to boot more cores than exist?
-        */
-       if (max_cpus > ncores)
-               max_cpus = ncores;
-
        /*
         * Initialise the present map, which describes the set of CPUs
         * actually populated at the present time.
@@ -164,27 +154,15 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
        for (i = 0; i < max_cpus; i++)
                set_cpu_present(i, true);
 
+       scu_enable(scu_base_addr());
+
        /*
-        * Initialise the SCU if there are more than one CPU and let
-        * them know where to start.
+        * Write the address of secondary startup into the
+        * system-wide flags register. The boot monitor waits
+        * until it receives a soft interrupt, and then the
+        * secondary CPU branches to this address.
         */
-       if (max_cpus > 1) {
-               /*
-                * Enable the local timer or broadcast device for the
-                * boot CPU, but only if we have more than one CPU.
-                */
-               percpu_timer_setup();
-
-               scu_enable(scu_base_addr());
-
-               /*
-                * Write the address of secondary startup into the
-                * system-wide flags register. The boot monitor waits
-                * until it receives a soft interrupt, and then the
-                * secondary CPU branches to this address.
-                */
-               writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
-               writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
-                       MMIO_P2V(V2M_SYS_FLAGSSET));
-       }
+       writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
+       writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
+               MMIO_P2V(V2M_SYS_FLAGSSET));
 }
index 7eaa232180a5ae627c3639ba642755444a5d3e27..a9ed3428a2fae616a75405c69692e38c2f3a7de4 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/sysdev.h>
 #include <linux/usb/isp1760.h>
+#include <linux/clkdev.h>
 
-#include <asm/clkdev.h>
 #include <asm/sizes.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/hardware/arm_timer.h>
+#include <asm/hardware/timer-sp.h>
 
-#include <mach/clkdev.h>
 #include <mach/motherboard.h>
 
-#include <plat/timer-sp.h>
+#include <plat/sched_clock.h>
 
 #include "core.h"
 
@@ -50,6 +50,8 @@ void __init v2m_map_io(struct map_desc *tile, size_t num)
 
 static void __init v2m_timer_init(void)
 {
+       versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
+
        writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
        writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
 
index c56ddab3d9128acce33ba0d293a3dcfa29bcd08c..b88a1b16b2e965b29c88417b0c153e662a382e5f 100644 (file)
@@ -10,7 +10,7 @@
  * the Free Software Foundation; either version 2 of the License.
  */
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 void nuc900_clk_enable(struct clk *clk, int enable);
 void nuc900_subclk_enable(struct clk *clk, int enable);
index b80f769bc1356509ca4fb36b198c5db13f245593..4b089cb930dc8f7dbcaddb3dc86a473bd03f4518 100644 (file)
@@ -153,7 +153,6 @@ static struct clocksource clocksource_nuc900 = {
        .rating = 200,
        .read   = nuc900_get_cycles,
        .mask   = CLOCKSOURCE_MASK(TDR_SHIFT),
-       .shift  = 10,
        .flags  = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -176,9 +175,7 @@ static void __init nuc900_clocksource_init(void)
        val |= (COUNTEN | PERIOD | PRESCALE);
        __raw_writel(val, REG_TCSR1);
 
-       clocksource_nuc900.mult =
-               clocksource_khz2mult((rate / 1000), clocksource_nuc900.shift);
-       clocksource_register(&clocksource_nuc900);
+       clocksource_register_hz(&clocksource_nuc900, rate);
 }
 
 static void __init nuc900_timer_init(void)
index a099efed0e63540fce62f98aac4290da87156d8f..49db8b3e4a497643ce3c9ec08268ca217e3d3b10 100644 (file)
@@ -605,6 +605,14 @@ config CPU_CP15_MPU
        help
          Processor has the CP15 register, which has MPU related registers.
 
+config CPU_USE_DOMAINS
+       bool
+       depends on MMU
+       default y if !CPU_32v6K
+       help
+         This option enables or disables the use of domain switching
+         via the set_fs() function.
+
 #
 # CPU supports 36-bit I/O
 #
@@ -634,6 +642,33 @@ config ARM_THUMBEE
          Say Y here if you have a CPU with the ThumbEE extension and code to
          make use of it. Say N for code that can run on CPUs without ThumbEE.
 
+config SWP_EMULATE
+       bool "Emulate SWP/SWPB instructions"
+       depends on CPU_V7
+       select HAVE_PROC_CPU if PROC_FS
+       default y if SMP
+       help
+         ARMv6 architecture deprecates use of the SWP/SWPB instructions.
+         ARMv7 multiprocessing extensions introduce the ability to disable
+         these instructions, triggering an undefined instruction exception
+         when executed. Say Y here to enable software emulation of these
+         instructions for userspace (not kernel) using LDREX/STREX.
+         Also creates /proc/cpu/swp_emulation for statistics.
+
+         In some older versions of glibc [<=2.8] SWP is used during futex
+         trylock() operations with the assumption that the code will not
+         be preempted. This invalid assumption may be more likely to fail
+         with SWP emulation enabled, leading to deadlock of the user
+         application.
+
+         NOTE: when accessing uncached shared regions, LDREX/STREX rely
+         on an external transaction monitoring block called a global
+         monitor to maintain update atomicity. If your system does not
+         implement a global monitor, this option can cause programs that
+         perform SWP operations to uncached memory to deadlock.
+
+         If unsure, say Y.
+
 config CPU_BIG_ENDIAN
        bool "Build big-endian kernel"
        depends on ARCH_SUPPORTS_BIG_ENDIAN
index d63b6c413758a23389cbb09ea1ab8686c61e56db..00d74a04af3afd91858d4512feb4191913efedd7 100644 (file)
@@ -5,8 +5,8 @@
 obj-y                          := dma-mapping.o extable.o fault.o init.o \
                                   iomap.o
 
-obj-$(CONFIG_MMU)              += fault-armv.o flush.o ioremap.o mmap.o \
-                                  pgd.o mmu.o vmregion.o
+obj-$(CONFIG_MMU)              += fault-armv.o flush.o idmap.o ioremap.o \
+                                  mmap.o pgd.o mmu.o vmregion.o
 
 ifneq ($(CONFIG_MMU),y)
 obj-y                          += nommu.o
index 6e77c042d8e9417ad5b9141c6eab37767693e3ed..e0b0e7a4ec68a3c577959e9116b9c7fa5d0be09d 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/highmem.h>
 #include <asm/cacheflush.h>
-#include <asm/kmap_types.h>
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
 #include <plat/cache-feroceon-l2.h>
-#include "mm.h"
 
 /*
  * Low-level cache maintenance operations.
  * between which we don't want to be preempted.
  */
 
-static inline unsigned long l2_start_va(unsigned long paddr)
+static inline unsigned long l2_get_va(unsigned long paddr)
 {
 #ifdef CONFIG_HIGHMEM
        /*
-        * Let's do our own fixmap stuff in a minimal way here.
         * Because range ops can't be done on physical addresses,
         * we simply install a virtual mapping for it only for the
         * TLB lookup to occur, hence no need to flush the untouched
-        * memory mapping.  This is protected with the disabling of
-        * interrupts by the caller.
+        * memory mapping afterwards (note: a cache flush may happen
+        * in some circumstances depending on the path taken in kunmap_atomic).
         */
-       unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
-       unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-       set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0);
-       local_flush_tlb_kernel_page(vaddr);
-       return vaddr + (paddr & ~PAGE_MASK);
+       void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT);
+       return (unsigned long)vaddr + (paddr & ~PAGE_MASK);
 #else
        return __phys_to_virt(paddr);
 #endif
 }
 
+static inline void l2_put_va(unsigned long vaddr)
+{
+#ifdef CONFIG_HIGHMEM
+       kunmap_atomic((void *)vaddr);
+#endif
+}
+
 static inline void l2_clean_pa(unsigned long addr)
 {
        __asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
@@ -76,13 +75,14 @@ static inline void l2_clean_pa_range(unsigned long start, unsigned long end)
         */
        BUG_ON((start ^ end) >> PAGE_SHIFT);
 
-       raw_local_irq_save(flags);
-       va_start = l2_start_va(start);
+       va_start = l2_get_va(start);
        va_end = va_start + (end - start);
+       raw_local_irq_save(flags);
        __asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
                "mcr p15, 1, %1, c15, c9, 5"
                : : "r" (va_start), "r" (va_end));
        raw_local_irq_restore(flags);
+       l2_put_va(va_start);
 }
 
 static inline void l2_clean_inv_pa(unsigned long addr)
@@ -106,13 +106,14 @@ static inline void l2_inv_pa_range(unsigned long start, unsigned long end)
         */
        BUG_ON((start ^ end) >> PAGE_SHIFT);
 
-       raw_local_irq_save(flags);
-       va_start = l2_start_va(start);
+       va_start = l2_get_va(start);
        va_end = va_start + (end - start);
+       raw_local_irq_save(flags);
        __asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
                "mcr p15, 1, %1, c15, c11, 5"
                : : "r" (va_start), "r" (va_end));
        raw_local_irq_restore(flags);
+       l2_put_va(va_start);
 }
 
 static inline void l2_inv_all(void)
index c3154928bccdf9750bef6da4e4fc29c2aad732f5..5a32020471e3bab2fc1e966a6e968c17a87f1d37 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 #include <linux/init.h>
+#include <linux/highmem.h>
 #include <asm/system.h>
 #include <asm/cputype.h>
 #include <asm/cacheflush.h>
-#include <asm/kmap_types.h>
-#include <asm/fixmap.h>
-#include <asm/pgtable.h>
-#include <asm/tlbflush.h>
-#include "mm.h"
 
 #define CR_L2  (1 << 26)
 
@@ -71,16 +67,15 @@ static inline void xsc3_l2_inv_all(void)
        dsb();
 }
 
+static inline void l2_unmap_va(unsigned long va)
+{
 #ifdef CONFIG_HIGHMEM
-#define l2_map_save_flags(x)           raw_local_save_flags(x)
-#define l2_map_restore_flags(x)                raw_local_irq_restore(x)
-#else
-#define l2_map_save_flags(x)           ((x) = 0)
-#define l2_map_restore_flags(x)                ((void)(x))
+       if (va != -1)
+               kunmap_atomic((void *)va);
 #endif
+}
 
-static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
-                                     unsigned long flags)
+static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va)
 {
 #ifdef CONFIG_HIGHMEM
        unsigned long va = prev_va & PAGE_MASK;
@@ -89,17 +84,10 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
                /*
                 * Switching to a new page.  Because cache ops are
                 * using virtual addresses only, we must put a mapping
-                * in place for it.  We also enable interrupts for a
-                * short while and disable them again to protect this
-                * mapping.
+                * in place for it.
                 */
-               unsigned long idx;
-               raw_local_irq_restore(flags);
-               idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
-               va = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-               raw_local_irq_restore(flags | PSR_I_BIT);
-               set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0);
-               local_flush_tlb_kernel_page(va);
+               l2_unmap_va(prev_va);
+               va = (unsigned long)kmap_atomic_pfn(pa >> PAGE_SHIFT);
        }
        return va + (pa_offset >> (32 - PAGE_SHIFT));
 #else
@@ -109,7 +97,7 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
 
 static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
 {
-       unsigned long vaddr, flags;
+       unsigned long vaddr;
 
        if (start == 0 && end == -1ul) {
                xsc3_l2_inv_all();
@@ -117,13 +105,12 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
        }
 
        vaddr = -1;  /* to force the first mapping */
-       l2_map_save_flags(flags);
 
        /*
         * Clean and invalidate partial first cache line.
         */
        if (start & (CACHE_LINE_SIZE - 1)) {
-               vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags);
+               vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr);
                xsc3_l2_clean_mva(vaddr);
                xsc3_l2_inv_mva(vaddr);
                start = (start | (CACHE_LINE_SIZE - 1)) + 1;
@@ -133,7 +120,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
         * Invalidate all full cache lines between 'start' and 'end'.
         */
        while (start < (end & ~(CACHE_LINE_SIZE - 1))) {
-               vaddr = l2_map_va(start, vaddr, flags);
+               vaddr = l2_map_va(start, vaddr);
                xsc3_l2_inv_mva(vaddr);
                start += CACHE_LINE_SIZE;
        }
@@ -142,31 +129,30 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
         * Clean and invalidate partial last cache line.
         */
        if (start < end) {
-               vaddr = l2_map_va(start, vaddr, flags);
+               vaddr = l2_map_va(start, vaddr);
                xsc3_l2_clean_mva(vaddr);
                xsc3_l2_inv_mva(vaddr);
        }
 
-       l2_map_restore_flags(flags);
+       l2_unmap_va(vaddr);
 
        dsb();
 }
 
 static void xsc3_l2_clean_range(unsigned long start, unsigned long end)
 {
-       unsigned long vaddr, flags;
+       unsigned long vaddr;
 
        vaddr = -1;  /* to force the first mapping */
-       l2_map_save_flags(flags);
 
        start &= ~(CACHE_LINE_SIZE - 1);
        while (start < end) {
-               vaddr = l2_map_va(start, vaddr, flags);
+               vaddr = l2_map_va(start, vaddr);
                xsc3_l2_clean_mva(vaddr);
                start += CACHE_LINE_SIZE;
        }
 
-       l2_map_restore_flags(flags);
+       l2_unmap_va(vaddr);
 
        dsb();
 }
@@ -193,7 +179,7 @@ static inline void xsc3_l2_flush_all(void)
 
 static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
 {
-       unsigned long vaddr, flags;
+       unsigned long vaddr;
 
        if (start == 0 && end == -1ul) {
                xsc3_l2_flush_all();
@@ -201,17 +187,16 @@ static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
        }
 
        vaddr = -1;  /* to force the first mapping */
-       l2_map_save_flags(flags);
 
        start &= ~(CACHE_LINE_SIZE - 1);
        while (start < end) {
-               vaddr = l2_map_va(start, vaddr, flags);
+               vaddr = l2_map_va(start, vaddr);
                xsc3_l2_clean_mva(vaddr);
                xsc3_l2_inv_mva(vaddr);
                start += CACHE_LINE_SIZE;
        }
 
-       l2_map_restore_flags(flags);
+       l2_unmap_va(vaddr);
 
        dsb();
 }
index ac6a36142fcd5a28084b3c669fac9e800fd65497..6b48e0a3d7aaaff0f8c65c3e60f1bae017873d51 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/highmem.h>
 
 #include <asm/memory.h>
 #include <asm/highmem.h>
@@ -311,7 +312,7 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
                addr = page_address(page);
 
        if (addr)
-               *handle = page_to_dma(dev, page);
+               *handle = pfn_to_dma(dev, page_to_pfn(page));
 
        return addr;
 }
@@ -406,7 +407,7 @@ void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr
        if (!arch_is_coherent())
                __dma_free_remap(cpu_addr, size);
 
-       __dma_free_buffer(dma_to_page(dev, handle), size);
+       __dma_free_buffer(pfn_to_page(dma_to_pfn(dev, handle)), size);
 }
 EXPORT_SYMBOL(dma_free_coherent);
 
@@ -480,10 +481,10 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
                                op(vaddr, len, dir);
                                kunmap_high(page);
                        } else if (cache_is_vipt()) {
-                               pte_t saved_pte;
-                               vaddr = kmap_high_l1_vipt(page, &saved_pte);
+                               /* unmapped pages might still be cached */
+                               vaddr = kmap_atomic(page);
                                op(vaddr + offset, len, dir);
-                               kunmap_high_l1_vipt(page, saved_pte);
+                               kunmap_atomic(vaddr);
                        }
                } else {
                        vaddr = page_address(page) + offset;
@@ -554,17 +555,20 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
        struct scatterlist *s;
        int i, j;
 
+       BUG_ON(!valid_dma_direction(dir));
+
        for_each_sg(sg, s, nents, i) {
-               s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
+               s->dma_address = __dma_map_page(dev, sg_page(s), s->offset,
                                                s->length, dir);
                if (dma_mapping_error(dev, s->dma_address))
                        goto bad_mapping;
        }
+       debug_dma_map_sg(dev, sg, nents, nents, dir);
        return nents;
 
  bad_mapping:
        for_each_sg(sg, s, i, j)
-               dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+               __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
        return 0;
 }
 EXPORT_SYMBOL(dma_map_sg);
@@ -585,8 +589,10 @@ void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
        struct scatterlist *s;
        int i;
 
+       debug_dma_unmap_sg(dev, sg, nents, dir);
+
        for_each_sg(sg, s, nents, i)
-               dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+               __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
 }
 EXPORT_SYMBOL(dma_unmap_sg);
 
@@ -611,6 +617,8 @@ void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
                __dma_page_dev_to_cpu(sg_page(s), s->offset,
                                      s->length, dir);
        }
+
+       debug_dma_sync_sg_for_cpu(dev, sg, nents, dir);
 }
 EXPORT_SYMBOL(dma_sync_sg_for_cpu);
 
@@ -635,5 +643,16 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
                __dma_page_cpu_to_dev(sg_page(s), s->offset,
                                      s->length, dir);
        }
+
+       debug_dma_sync_sg_for_device(dev, sg, nents, dir);
 }
 EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES     4096
+
+static int __init dma_debug_do_init(void)
+{
+       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+       return 0;
+}
+fs_initcall(dma_debug_do_init);
index 83e59f8704261bfa1c12bd2cd21ac0c21ad17e08..01210dba02217302a3757ecc93810d46d089d43a 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "mm.h"
 
-static unsigned long shared_pte_mask = L_PTE_MT_BUFFERABLE;
+static pteval_t shared_pte_mask = L_PTE_MT_BUFFERABLE;
 
 #if __LINUX_ARM_ARCH__ < 6
 /*
index 1e21e125fe3a833fadcc932c8fcf01177d7ba8f2..f10f9bac220695d02037731e6715ad510bbfb33d 100644 (file)
@@ -108,7 +108,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
 
                pte = pte_offset_map(pmd, addr);
                printk(", *pte=%08lx", pte_val(*pte));
-               printk(", *ppte=%08lx", pte_val(pte[-PTRS_PER_PTE]));
+               printk(", *ppte=%08lx", pte_val(pte[PTE_HWTABLE_PTRS]));
                pte_unmap(pte);
        } while(0);
 
index 391ffae750986404df8658d53e93fdc69b970ba4..c29f2839f1d2b72c8aa99e17db44e120a42bc7ee 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/pagemap.h>
+#include <linux/highmem.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cachetype.h>
@@ -180,10 +181,10 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
                        __cpuc_flush_dcache_area(addr, PAGE_SIZE);
                        kunmap_high(page);
                } else if (cache_is_vipt()) {
-                       pte_t saved_pte;
-                       addr = kmap_high_l1_vipt(page, &saved_pte);
+                       /* unmapped pages might still be cached */
+                       addr = kmap_atomic(page);
                        __cpuc_flush_dcache_area(addr, PAGE_SIZE);
-                       kunmap_high_l1_vipt(page, saved_pte);
+                       kunmap_atomic(addr);
                }
        }
 
index c435fd9e1da95c9fdc9d7fab83b3a42caef1b905..807c0573abbe82533a884f87ea7ea243051a228d 100644 (file)
@@ -140,90 +140,3 @@ struct page *kmap_atomic_to_page(const void *ptr)
        pte = TOP_PTE(vaddr);
        return pte_page(*pte);
 }
-
-#ifdef CONFIG_CPU_CACHE_VIPT
-
-#include <linux/percpu.h>
-
-/*
- * The VIVT cache of a highmem page is always flushed before the page
- * is unmapped. Hence unmapped highmem pages need no cache maintenance
- * in that case.
- *
- * However unmapped pages may still be cached with a VIPT cache, and
- * it is not possible to perform cache maintenance on them using physical
- * addresses unfortunately.  So we have no choice but to set up a temporary
- * virtual mapping for that purpose.
- *
- * Yet this VIPT cache maintenance may be triggered from DMA support
- * functions which are possibly called from interrupt context. As we don't
- * want to keep interrupt disabled all the time when such maintenance is
- * taking place, we therefore allow for some reentrancy by preserving and
- * restoring the previous fixmap entry before the interrupted context is
- * resumed.  If the reentrancy depth is 0 then there is no need to restore
- * the previous fixmap, and leaving the current one in place allow it to
- * be reused the next time without a TLB flush (common with DMA).
- */
-
-static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);
-
-void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte)
-{
-       unsigned int idx, cpu;
-       int *depth;
-       unsigned long vaddr, flags;
-       pte_t pte, *ptep;
-
-       if (!in_interrupt())
-               preempt_disable();
-
-       cpu = smp_processor_id();
-       depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
-
-       idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
-       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-       ptep = TOP_PTE(vaddr);
-       pte = mk_pte(page, kmap_prot);
-
-       raw_local_irq_save(flags);
-       (*depth)++;
-       if (pte_val(*ptep) == pte_val(pte)) {
-               *saved_pte = pte;
-       } else {
-               *saved_pte = *ptep;
-               set_pte_ext(ptep, pte, 0);
-               local_flush_tlb_kernel_page(vaddr);
-       }
-       raw_local_irq_restore(flags);
-
-       return (void *)vaddr;
-}
-
-void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte)
-{
-       unsigned int idx, cpu = smp_processor_id();
-       int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
-       unsigned long vaddr, flags;
-       pte_t pte, *ptep;
-
-       idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
-       vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
-       ptep = TOP_PTE(vaddr);
-       pte = mk_pte(page, kmap_prot);
-
-       BUG_ON(pte_val(*ptep) != pte_val(pte));
-       BUG_ON(*depth <= 0);
-
-       raw_local_irq_save(flags);
-       (*depth)--;
-       if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) {
-               set_pte_ext(ptep, saved_pte, 0);
-               local_flush_tlb_kernel_page(vaddr);
-       }
-       raw_local_irq_restore(flags);
-
-       if (!in_interrupt())
-               preempt_enable();
-}
-
-#endif  /* CONFIG_CPU_CACHE_VIPT */
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
new file mode 100644 (file)
index 0000000..5729944
--- /dev/null
@@ -0,0 +1,67 @@
+#include <linux/kernel.h>
+
+#include <asm/cputype.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+
+static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end,
+       unsigned long prot)
+{
+       pmd_t *pmd = pmd_offset(pgd, addr);
+
+       addr = (addr & PMD_MASK) | prot;
+       pmd[0] = __pmd(addr);
+       addr += SECTION_SIZE;
+       pmd[1] = __pmd(addr);
+       flush_pmd_entry(pmd);
+}
+
+void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+       unsigned long prot, next;
+
+       prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE;
+       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
+               prot |= PMD_BIT4;
+
+       pgd += pgd_index(addr);
+       do {
+               next = pgd_addr_end(addr, end);
+               idmap_add_pmd(pgd, addr, next, prot);
+       } while (pgd++, addr = next, addr != end);
+}
+
+#ifdef CONFIG_SMP
+static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+       pmd_t *pmd = pmd_offset(pgd, addr);
+       pmd_clear(pmd);
+}
+
+void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+       unsigned long next;
+
+       pgd += pgd_index(addr);
+       do {
+               next = pgd_addr_end(addr, end);
+               idmap_del_pmd(pgd, addr, next);
+       } while (pgd++, addr = next, addr != end);
+}
+#endif
+
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages.  This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void setup_mm_for_reboot(char mode)
+{
+       /*
+        * We need to access to user-mode page tables here. For kernel threads
+        * we don't have any user-mode mappings so we use the context that we
+        * "borrowed".
+        */
+       identity_mapping_add(current->active_mm->pgd, 0, TASK_SIZE);
+       local_flush_tlb_all();
+}
index 55c17a6fb22fba2450ebce975a467f6c33ddf0ea..ab506272b2d3ef459b264b7741d61af46f6aa6b8 100644 (file)
@@ -204,12 +204,8 @@ void __iomem * __arm_ioremap_pfn_caller(unsigned long pfn,
        /*
         * Don't allow RAM to be mapped - this causes problems with ARMv6+
         */
-       if (pfn_valid(pfn)) {
-               printk(KERN_WARNING "BUG: Your driver calls ioremap() on system memory.  This leads\n"
-                      "to architecturally unpredictable behaviour on ARMv6+, and ioremap()\n"
-                      "will fail in the next kernel release.  Please fix your driver.\n");
-               WARN_ON(1);
-       }
+       if (WARN_ON(pfn_valid(pfn)))
+               return NULL;
 
        type = get_mem_type(mtype);
        if (!type)
index 6630620380a4aa0f538aed006a2de6f04c71d3dd..36960df5fb762a990be65bba9d92efba3657d8ed 100644 (file)
@@ -16,7 +16,7 @@ static inline pmd_t *pmd_off_k(unsigned long virt)
 }
 
 struct mem_type {
-       unsigned int prot_pte;
+       pteval_t prot_pte;
        unsigned int prot_l1;
        unsigned int prot_sect;
        unsigned int domain;
index 72ad3e1f56cfb704e800a2e109f5eea7f66017a4..3c67e92f7d5921183e69d21e507d854aac8cde94 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/smp_plat.h>
 #include <asm/tlb.h>
 #include <asm/highmem.h>
+#include <asm/traps.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -62,7 +63,7 @@ struct cachepolicy {
        const char      policy[16];
        unsigned int    cr_mask;
        unsigned int    pmd;
-       unsigned int    pte;
+       pteval_t        pte;
 };
 
 static struct cachepolicy cache_policies[] __initdata = {
@@ -190,7 +191,7 @@ void adjust_cr(unsigned long mask, unsigned long set)
 }
 #endif
 
-#define PROT_PTE_DEVICE                L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_WRITE
+#define PROT_PTE_DEVICE                L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
 #define PROT_SECT_DEVICE       PMD_TYPE_SECT|PMD_SECT_AP_WRITE
 
 static struct mem_type mem_types[] = {
@@ -235,19 +236,18 @@ static struct mem_type mem_types[] = {
        },
        [MT_LOW_VECTORS] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_EXEC,
+                               L_PTE_RDONLY,
                .prot_l1   = PMD_TYPE_TABLE,
                .domain    = DOMAIN_USER,
        },
        [MT_HIGH_VECTORS] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_USER | L_PTE_EXEC,
+                               L_PTE_USER | L_PTE_RDONLY,
                .prot_l1   = PMD_TYPE_TABLE,
                .domain    = DOMAIN_USER,
        },
        [MT_MEMORY] = {
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_WRITE | L_PTE_EXEC,
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
                .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
                .domain    = DOMAIN_KERNEL,
@@ -258,21 +258,20 @@ static struct mem_type mem_types[] = {
        },
        [MT_MEMORY_NONCACHED] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_WRITE | L_PTE_EXEC | L_PTE_MT_BUFFERABLE,
+                               L_PTE_MT_BUFFERABLE,
                .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
                .domain    = DOMAIN_KERNEL,
        },
        [MT_MEMORY_DTCM] = {
                .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_WRITE,
+                               L_PTE_XN,
                .prot_l1   = PMD_TYPE_TABLE,
                .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
                .domain    = DOMAIN_KERNEL,
        },
        [MT_MEMORY_ITCM] = {
-               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-                               L_PTE_WRITE | L_PTE_EXEC,
+               .prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
                .prot_l1   = PMD_TYPE_TABLE,
                .domain    = DOMAIN_KERNEL,
        },
@@ -479,7 +478,7 @@ static void __init build_mem_type_table(void)
 
        pgprot_user   = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
        pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
-                                L_PTE_DIRTY | L_PTE_WRITE | kern_pgprot);
+                                L_PTE_DIRTY | kern_pgprot);
 
        mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
        mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
@@ -535,7 +534,7 @@ static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned l
 {
        if (pmd_none(*pmd)) {
                pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t));
-               __pmd_populate(pmd, __pa(pte) | prot);
+               __pmd_populate(pmd, __pa(pte), prot);
        }
        BUG_ON(pmd_bad(*pmd));
        return pte_offset_kernel(pmd, addr);
@@ -553,7 +552,7 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
 }
 
 static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
-                                     unsigned long end, unsigned long phys,
+                                     unsigned long end, phys_addr_t phys,
                                      const struct mem_type *type)
 {
        pmd_t *pmd = pmd_offset(pgd, addr);
@@ -588,7 +587,8 @@ static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
 static void __init create_36bit_mapping(struct map_desc *md,
                                        const struct mem_type *type)
 {
-       unsigned long phys, addr, length, end;
+       unsigned long addr, length, end;
+       phys_addr_t phys;
        pgd_t *pgd;
 
        addr = md->virtual;
@@ -914,12 +914,11 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
 {
        struct map_desc map;
        unsigned long addr;
-       void *vectors;
 
        /*
         * Allocate the vector page early.
         */
-       vectors = early_alloc(PAGE_SIZE);
+       vectors_page = early_alloc(PAGE_SIZE);
 
        for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
                pmd_clear(pmd_off_k(addr));
@@ -959,7 +958,7 @@ static void __init devicemaps_init(struct machine_desc *mdesc)
         * location (0xffff0000).  If we aren't using high-vectors, also
         * create a mapping at the low-vectors virtual address.
         */
-       map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+       map.pfn = __phys_to_pfn(virt_to_phys(vectors_page));
        map.virtual = 0xffff0000;
        map.length = PAGE_SIZE;
        map.type = MT_HIGH_VECTORS;
@@ -1044,38 +1043,3 @@ void __init paging_init(struct machine_desc *mdesc)
        empty_zero_page = virt_to_page(zero_page);
        __flush_dcache_page(NULL, empty_zero_page);
 }
-
-/*
- * In order to soft-boot, we need to insert a 1:1 mapping in place of
- * the user-mode pages.  This will then ensure that we have predictable
- * results when turning the mmu off
- */
-void setup_mm_for_reboot(char mode)
-{
-       unsigned long base_pmdval;
-       pgd_t *pgd;
-       int i;
-
-       /*
-        * We need to access to user-mode page tables here. For kernel threads
-        * we don't have any user-mode mappings so we use the context that we
-        * "borrowed".
-        */
-       pgd = current->active_mm->pgd;
-
-       base_pmdval = PMD_SECT_AP_WRITE | PMD_SECT_AP_READ | PMD_TYPE_SECT;
-       if (cpu_architecture() <= CPU_ARCH_ARMv5TEJ && !cpu_is_xscale())
-               base_pmdval |= PMD_BIT4;
-
-       for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
-               unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
-               pmd_t *pmd;
-
-               pmd = pmd_off(pgd, i << PGDIR_SHIFT);
-               pmd[0] = __pmd(pmdval);
-               pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
-               flush_pmd_entry(pmd);
-       }
-
-       local_flush_tlb_all();
-}
index 69bbfc6645a673853ed6f8171e08e3a4f9f22585..93292a18cf77f35bd9369ad84f3f6f56e948ddc8 100644 (file)
 
 #include "mm.h"
 
-#define FIRST_KERNEL_PGD_NR    (FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
-
 /*
  * need to get a 16k page for level 1
  */
-pgd_t *get_pgd_slow(struct mm_struct *mm)
+pgd_t *pgd_alloc(struct mm_struct *mm)
 {
        pgd_t *new_pgd, *init_pgd;
        pmd_t *new_pmd, *init_pmd;
@@ -32,14 +30,14 @@ pgd_t *get_pgd_slow(struct mm_struct *mm)
        if (!new_pgd)
                goto no_pgd;
 
-       memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
+       memset(new_pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
 
        /*
         * Copy over the kernel and IO PGD entries
         */
        init_pgd = pgd_offset_k(0);
-       memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
-                      (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
+       memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
+                      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 
        clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
 
@@ -73,28 +71,29 @@ no_pgd:
        return NULL;
 }
 
-void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
+void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
 {
+       pgd_t *pgd;
        pmd_t *pmd;
        pgtable_t pte;
 
-       if (!pgd)
+       if (!pgd_base)
                return;
 
-       /* pgd is always present and good */
-       pmd = pmd_off(pgd, 0);
-       if (pmd_none(*pmd))
-               goto free;
-       if (pmd_bad(*pmd)) {
-               pmd_ERROR(*pmd);
-               pmd_clear(pmd);
-               goto free;
-       }
+       pgd = pgd_base + pgd_index(0);
+       if (pgd_none_or_clear_bad(pgd))
+               goto no_pgd;
+
+       pmd = pmd_offset(pgd, 0);
+       if (pmd_none_or_clear_bad(pmd))
+               goto no_pmd;
 
        pte = pmd_pgtable(*pmd);
        pmd_clear(pmd);
        pte_free(mm, pte);
+no_pmd:
+       pgd_clear(pgd);
        pmd_free(mm, pmd);
-free:
-       free_pages((unsigned long) pgd, 2);
+no_pgd:
+       free_pages((unsigned long) pgd_base, 2);
 }
index b795afd0a2c620ad1e8f774b1c166bc8639b2847..e32fa499194ca717b27a3391bf0c71879ad4a352 100644 (file)
@@ -91,7 +91,7 @@
 #if L_PTE_SHARED != PTE_EXT_SHARED
 #error PTE shared bit mismatch
 #endif
-#if (L_PTE_EXEC+L_PTE_USER+L_PTE_WRITE+L_PTE_DIRTY+L_PTE_YOUNG+\
+#if (L_PTE_XN+L_PTE_USER+L_PTE_RDONLY+L_PTE_DIRTY+L_PTE_YOUNG+\
      L_PTE_FILE+L_PTE_PRESENT) > L_PTE_SHARED
 #error Invalid Linux PTE bit settings
 #endif
  *  110x   0   1   0   r/w     r/o
  *  11x0   0   1   0   r/w     r/o
  *  1111   0   1   1   r/w     r/w
+ *
+ * If !CONFIG_CPU_USE_DOMAINS, the following permissions are changed:
+ *  110x   1   1   1   r/o     r/o
+ *  11x0   1   1   1   r/o     r/o
  */
        .macro  armv6_mt_table pfx
 \pfx\()_mt_table:
        .endm
 
        .macro  armv6_set_pte_ext pfx
-       str     r1, [r0], #-2048                @ linux version
+       str     r1, [r0], #2048                 @ linux version
 
        bic     r3, r1, #0x000003fc
        bic     r3, r3, #PTE_TYPE_MASK
        and     r2, r1, #L_PTE_MT_MASK
        ldr     r2, [ip, r2]
 
-       tst     r1, #L_PTE_WRITE
-       tstne   r1, #L_PTE_DIRTY
-       orreq   r3, r3, #PTE_EXT_APX
+       eor     r1, r1, #L_PTE_DIRTY
+       tst     r1, #L_PTE_DIRTY|L_PTE_RDONLY
+       orrne   r3, r3, #PTE_EXT_APX
 
        tst     r1, #L_PTE_USER
        orrne   r3, r3, #PTE_EXT_AP1
+#ifdef CONFIG_CPU_USE_DOMAINS
+       @ allow kernel read/write access to read-only user pages
        tstne   r3, #PTE_EXT_APX
        bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+#endif
 
-       tst     r1, #L_PTE_EXEC
-       orreq   r3, r3, #PTE_EXT_XN
+       tst     r1, #L_PTE_XN
+       orrne   r3, r3, #PTE_EXT_XN
 
        orr     r3, r3, r2
 
  *  1111  0xff r/w     r/w
  */
        .macro  armv3_set_pte_ext wc_disable=1
-       str     r1, [r0], #-2048                @ linux version
+       str     r1, [r0], #2048                 @ linux version
 
-       eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+       eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY
 
        bic     r2, r1, #PTE_SMALL_AP_MASK      @ keep C, B bits
        bic     r2, r2, #PTE_TYPE_MASK
        tst     r3, #L_PTE_USER                 @ user?
        orrne   r2, r2, #PTE_SMALL_AP_URO_SRW
 
-       tst     r3, #L_PTE_WRITE | L_PTE_DIRTY  @ write and dirty?
+       tst     r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty?
        orreq   r2, r2, #PTE_SMALL_AP_UNO_SRW
 
        tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ present and young?
        bicne   r2, r2, #PTE_BUFFERABLE
 #endif
        .endif
-       str     r2, [r0]                        @ hardware version
+       str     r2, [r0]                @ hardware version
        .endm
 
 
  *  1111  11   r/w     r/w
  */
        .macro  xscale_set_pte_ext_prologue
-       str     r1, [r0], #-2048                @ linux version
+       str     r1, [r0]                        @ linux version
 
-       eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_WRITE | L_PTE_DIRTY
+       eor     r3, r1, #L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY
 
        bic     r2, r1, #PTE_SMALL_AP_MASK      @ keep C, B bits
        orr     r2, r2, #PTE_TYPE_EXT           @ extended page
        tst     r3, #L_PTE_USER                 @ user?
        orrne   r2, r2, #PTE_EXT_AP_URO_SRW     @ yes -> user r/o, system r/w
 
-       tst     r3, #L_PTE_WRITE | L_PTE_DIRTY  @ write and dirty?
+       tst     r3, #L_PTE_RDONLY | L_PTE_DIRTY @ write and dirty?
        orreq   r2, r2, #PTE_EXT_AP_UNO_SRW     @ yes -> user n/a, system r/w
                                                @ combined with user -> user r/w
        .endm
        tst     r3, #L_PTE_PRESENT | L_PTE_YOUNG        @ present and young?
        movne   r2, #0                          @ no -> fault
 
-       str     r2, [r0]                        @ hardware version
+       str     r2, [r0, #2048]!                @ hardware version
        mov     ip, #0
        mcr     p15, 0, r0, c7, c10, 1          @ clean L1 D line
        mcr     p15, 0, ip, c7, c10, 4          @ data write barrier
index 9b9ff5d949fdd08d73d37351b0e3c580a7533b83..b49fab21517c04b1f0d7476571a05b7133ca4826 100644 (file)
@@ -124,15 +124,13 @@ ENDPROC(cpu_v7_switch_mm)
  *     Set a level 2 translation table entry.
  *
  *     - ptep  - pointer to level 2 translation table entry
- *               (hardware version is stored at -1024 bytes)
+ *               (hardware version is stored at +2048 bytes)
  *     - pte   - PTE value to store
  *     - ext   - value for extended PTE bits
  */
 ENTRY(cpu_v7_set_pte_ext)
 #ifdef CONFIG_MMU
- ARM(  str     r1, [r0], #-2048        )       @ linux version
- THUMB(        str     r1, [r0]                )       @ linux version
- THUMB(        sub     r0, r0, #2048           )
+       str     r1, [r0]                        @ linux version
 
        bic     r3, r1, #0x000003f0
        bic     r3, r3, #PTE_TYPE_MASK
@@ -142,23 +140,26 @@ ENTRY(cpu_v7_set_pte_ext)
        tst     r1, #1 << 4
        orrne   r3, r3, #PTE_EXT_TEX(1)
 
-       tst     r1, #L_PTE_WRITE
-       tstne   r1, #L_PTE_DIRTY
-       orreq   r3, r3, #PTE_EXT_APX
+       eor     r1, r1, #L_PTE_DIRTY
+       tst     r1, #L_PTE_RDONLY | L_PTE_DIRTY
+       orrne   r3, r3, #PTE_EXT_APX
 
        tst     r1, #L_PTE_USER
        orrne   r3, r3, #PTE_EXT_AP1
+#ifdef CONFIG_CPU_USE_DOMAINS
+       @ allow kernel read/write access to read-only user pages
        tstne   r3, #PTE_EXT_APX
        bicne   r3, r3, #PTE_EXT_APX | PTE_EXT_AP0
+#endif
 
-       tst     r1, #L_PTE_EXEC
-       orreq   r3, r3, #PTE_EXT_XN
+       tst     r1, #L_PTE_XN
+       orrne   r3, r3, #PTE_EXT_XN
 
        tst     r1, #L_PTE_YOUNG
        tstne   r1, #L_PTE_PRESENT
        moveq   r3, #0
 
-       str     r3, [r0]
+       str     r3, [r0, #2048]!
        mcr     p15, 0, r0, c7, c10, 1          @ flush_pte
 #endif
        mov     pc, lr
@@ -273,8 +274,6 @@ __v7_setup:
        ALT_SMP(orr     r4, r4, #TTB_FLAGS_SMP)
        ALT_UP(orr      r4, r4, #TTB_FLAGS_UP)
        mcr     p15, 0, r4, c2, c0, 1           @ load TTB1
-       mov     r10, #0x1f                      @ domains 0, 1 = manager
-       mcr     p15, 0, r10, c3, c0, 0          @ load domain access register
        /*
         * Memory region attributes with SCTLR.TRE=1
         *
@@ -312,6 +311,10 @@ __v7_setup:
        ldmia   r5, {r5, r6}
 #ifdef CONFIG_CPU_ENDIAN_BE8
        orr     r6, r6, #1 << 25                @ big-endian page tables
+#endif
+#ifdef CONFIG_SWP_EMULATE
+       orr     r5, r5, #(1 << 10)              @ set SW bit in "clear"
+       bic     r6, r6, #(1 << 10)              @ clear it in "mmuset"
 #endif
        mrc     p15, 0, r0, c1, c0, 0           @ read control register
        bic     r0, r0, r5                      @ clear bits them
index 523408c0bb38aafb69903dbd85f8584d5eef1a3a..5a37c5e45c411a8d377dec497207777338ed68db 100644 (file)
@@ -500,8 +500,8 @@ ENTRY(cpu_xscale_set_pte_ext)
        @
        @ Erratum 40: must set memory to write-through for user read-only pages
        @
-       and     ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_WRITE) & ~(4 << 2)
-       teq     ip, #L_PTE_MT_WRITEBACK | L_PTE_USER
+       and     ip, r1, #(L_PTE_MT_MASK | L_PTE_USER | L_PTE_RDONLY) & ~(4 << 2)
+       teq     ip, #L_PTE_MT_WRITEBACK | L_PTE_USER | L_PTE_RDONLY
 
        moveq   r1, #L_PTE_MT_WRITETHROUGH
        and     r1, r1, #L_PTE_MT_MASK
index 558cdfaf76b6a22a4ff6ff3a5190263c662a3268..07f23bb42bed4c4d4a47cce31b018709fabe0a61 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/timex.h>
 #include <linux/sched.h>
 #include <linux/io.h>
@@ -24,6 +25,7 @@
 #include <linux/clockchips.h>
 #include <mach/hardware.h>
 #include <asm/irq.h>
+#include <asm/sched_clock.h>
 #include <asm/uaccess.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
@@ -50,15 +52,21 @@ static struct clocksource iop_clocksource = {
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static DEFINE_CLOCK_DATA(cd);
+
 /*
  * IOP sched_clock() implementation via its clocksource.
  */
-unsigned long long sched_clock(void)
+unsigned long long notrace sched_clock(void)
 {
-       cycle_t cyc = iop_clocksource_read(NULL);
-       struct clocksource *cs = &iop_clocksource;
+       u32 cyc = 0xffffffffu - read_tcr1();
+       return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
 
-       return clocksource_cyc2ns(cyc, cs->mult, cs->shift);
+static void notrace iop_update_sched_clock(void)
+{
+       u32 cyc = 0xffffffffu - read_tcr1();
+       update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 /*
@@ -88,6 +96,7 @@ static void iop_set_mode(enum clock_event_mode mode,
        case CLOCK_EVT_MODE_PERIODIC:
                write_tmr0(tmr & ~IOP_TMR_EN);
                write_tcr0(ticks_per_jiffy - 1);
+               write_trr0(ticks_per_jiffy - 1);
                tmr |= (IOP_TMR_RELOAD | IOP_TMR_EN);
                break;
        case CLOCK_EVT_MODE_ONESHOT:
@@ -143,6 +152,8 @@ void __init iop_init_time(unsigned long tick_rate)
 {
        u32 timer_ctl;
 
+       init_sched_clock(&cd, iop_update_sched_clock, 32, tick_rate);
+
        ticks_per_jiffy = DIV_ROUND_CLOSEST(tick_rate, HZ);
        iop_tick_rate = tick_rate;
 
@@ -153,6 +164,7 @@ void __init iop_init_time(unsigned long tick_rate)
         * Set up interrupting clockevent timer 0.
         */
        write_tmr0(timer_ctl & ~IOP_TMR_EN);
+       write_tisr(1);
        setup_irq(IRQ_IOP_TIMER0, &iop_timer_irq);
        clockevents_calc_mult_shift(&iop_clockevent,
                                    tick_rate, IOP_MIN_RANGE);
@@ -162,9 +174,6 @@ void __init iop_init_time(unsigned long tick_rate)
                clockevent_delta2ns(0xf, &iop_clockevent);
        iop_clockevent.cpumask = cpumask_of(0);
        clockevents_register_device(&iop_clockevent);
-       write_trr0(ticks_per_jiffy - 1);
-       write_tcr0(ticks_per_jiffy - 1);
-       write_tmr0(timer_ctl);
 
        /*
         * Set up free-running clocksource timer 1.
@@ -172,7 +181,5 @@ void __init iop_init_time(unsigned long tick_rate)
        write_trr1(0xffffffff);
        write_tcr1(0xffffffff);
        write_tmr1(timer_ctl);
-       clocksource_calc_mult_shift(&iop_clocksource, tick_rate,
-                                   IOP_MIN_RANGE);
-       clocksource_register(&iop_clocksource);
+       clocksource_register_hz(&iop_clocksource, tick_rate);
 }
index ee9582f4972e87da83c0d6c29d196e31dd612651..d69d343ff61f1989cdfb1982b000eccc9aeb8d1d 100644 (file)
@@ -93,7 +93,6 @@ static struct clocksource clocksource_epit = {
        .rating         = 200,
        .read           = epit_read,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -101,9 +100,7 @@ static int __init epit_clocksource_init(struct clk *timer_clk)
 {
        unsigned int c = clk_get_rate(timer_clk);
 
-       clocksource_epit.mult = clocksource_hz2mult(c,
-                                       clocksource_epit.shift);
-       clocksource_register(&clocksource_epit);
+       clocksource_register_hz(&clocksource_epit, c);
 
        return 0;
 }
index f9a1b059a76cde1926f50758200c046f27685e7d..9f0c2610595ef5e282059e981278af5fdd0985fb 100644 (file)
@@ -120,7 +120,6 @@ static struct clocksource clocksource_mxc = {
        .rating         = 200,
        .read           = mx1_2_get_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 20,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -131,9 +130,7 @@ static int __init mxc_clocksource_init(struct clk *timer_clk)
        if (timer_is_v2())
                clocksource_mxc.read = v2_get_cycles;
 
-       clocksource_mxc.mult = clocksource_hz2mult(c,
-                                       clocksource_mxc.shift);
-       clocksource_register(&clocksource_mxc);
+       clocksource_register_hz(&clocksource_mxc, c);
 
        return 0;
 }
index 5da3f97c537be387c4b807e21ba2101dff47bb19..187f4e84bb220fd8f9a804251e33688c9ae5917c 100644 (file)
@@ -14,6 +14,7 @@ if PLAT_NOMADIK
 
 config HAS_MTU
        bool
+       select HAVE_SCHED_CLOCK
        help
          Support for Multi Timer Unit. MTU provides access
          to multiple interrupt generating programmable
index 63cdc6025bd74dfaf46bc93ec49125e9f75bb49d..41723402006b44d932d40f9c216d36f99911f10b 100644 (file)
@@ -17,9 +17,9 @@
 #include <linux/clk.h>
 #include <linux/jiffies.h>
 #include <linux/err.h>
-#include <linux/cnt32_to_63.h>
-#include <linux/timer.h>
+#include <linux/sched.h>
 #include <asm/mach/time.h>
+#include <asm/sched_clock.h>
 
 #include <plat/mtu.h>
 
@@ -52,81 +52,24 @@ static struct clocksource nmdk_clksrc = {
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
  * better resolution when scheduling the kernel.
- *
- * Because the hardware timer period may be quite short
- * (32.3 secs on the 133 MHz MTU timer selection on ux500)
- * and because cnt32_to_63() needs to be called at least once per
- * half period to work properly, a kernel keepwarm() timer is set up
- * to ensure this requirement is always met.
- *
- * Also the sched_clock timer will wrap around at some point,
- * here we set it to run continously for a year.
  */
-#define SCHED_CLOCK_MIN_WRAP 3600*24*365
-static struct timer_list cnt32_to_63_keepwarm_timer;
-static u32 sched_mult;
-static u32 sched_shift;
+static DEFINE_CLOCK_DATA(cd);
 
 unsigned long long notrace sched_clock(void)
 {
-       u64 cycles;
+       u32 cyc;
 
        if (unlikely(!mtu_base))
                return 0;
 
-       cycles = cnt32_to_63(-readl(mtu_base + MTU_VAL(0)));
-       /*
-        * sched_mult is guaranteed to be even so will
-        * shift out bit 63
-        */
-       return (cycles * sched_mult) >> sched_shift;
+       cyc = -readl(mtu_base + MTU_VAL(0));
+       return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
-/* Just kick sched_clock every so often */
-static void cnt32_to_63_keepwarm(unsigned long data)
+static void notrace nomadik_update_sched_clock(void)
 {
-       mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
-       (void) sched_clock();
-}
-
-/*
- * Set up a timer to keep sched_clock():s 32_to_63 algorithm warm
- * once in half a 32bit timer wrap interval.
- */
-static void __init nmdk_sched_clock_init(unsigned long rate)
-{
-       u32 v;
-       unsigned long delta;
-       u64 days;
-
-       /* Find the apropriate mult and shift factors */
-       clocks_calc_mult_shift(&sched_mult, &sched_shift,
-                              rate, NSEC_PER_SEC, SCHED_CLOCK_MIN_WRAP);
-       /* We need to multiply by an even number to get rid of bit 63 */
-       if (sched_mult & 1)
-               sched_mult++;
-
-       /* Let's see what we get, take max counter and scale it */
-       days = (0xFFFFFFFFFFFFFFFFLLU * sched_mult) >> sched_shift;
-       do_div(days, NSEC_PER_SEC);
-       do_div(days, (3600*24));
-
-       pr_info("sched_clock: using %d bits @ %lu Hz wrap in %lu days\n",
-               (64 - sched_shift), rate, (unsigned long) days);
-
-       /*
-        * Program a timer to kick us at half 32bit wraparound
-        * Formula: seconds per wrap = (2^32) / f
-        */
-       v = 0xFFFFFFFFUL / rate;
-       /* We want half of the wrap time to keep cnt32_to_63 warm */
-       v /= 2;
-       pr_debug("sched_clock: prescaled timer rate: %lu Hz, "
-                "initialize keepwarm timer every %d seconds\n", rate, v);
-       /* Convert seconds to jiffies */
-       delta = msecs_to_jiffies(v*1000);
-       setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, delta);
-       mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + delta));
+       u32 cyc = -readl(mtu_base + MTU_VAL(0));
+       update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 /* Clockevent device: use one-shot mode */
@@ -222,7 +165,6 @@ void __init nmdk_timer_init(void)
        } else {
                cr |= MTU_CRn_PRESCALE_1;
        }
-       clocksource_calc_mult_shift(&nmdk_clksrc, rate, MTU_MIN_RANGE);
 
        /* Timer 0 is the free running clocksource */
        writel(cr, mtu_base + MTU_CR(0));
@@ -233,11 +175,11 @@ void __init nmdk_timer_init(void)
        /* Now the clock source is ready */
        nmdk_clksrc.read = nmdk_read_timer;
 
-       if (clocksource_register(&nmdk_clksrc))
+       if (clocksource_register_hz(&nmdk_clksrc, rate))
                pr_err("timer: failed to initialize clock source %s\n",
                       nmdk_clksrc.name);
 
-       nmdk_sched_clock_init(rate);
+       init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
 
        /* Timer 1 is used for events */
 
index 92c5bb7909f5632c6d0132813292e655a1d16161..c9408434a855ecaf648c63cbc83efb4699f3a5f2 100644 (file)
@@ -11,13 +11,13 @@ choice
 
 config ARCH_OMAP1
        bool "TI OMAP1"
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        help
          "Systems based on omap7xx, omap15xx or omap16xx"
 
 config ARCH_OMAP2PLUS
        bool "TI OMAP2/3/4"
-       select COMMON_CLKDEV
+       select CLKDEV_LOOKUP
        help
          "Systems based on OMAP2, OMAP3 or OMAP4"
 
index 8722a136f3a5bee844f5643dd195c95f077db666..ea4644021fb9c0867c2e4ca4bd4bcb118e863f80 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/clk.h>
-#include <linux/io.h>
 #include <linux/err.h>
+#include <linux/io.h>
+#include <linux/sched.h>
+
+#include <asm/sched_clock.h>
 
 #include <plat/common.h>
 #include <plat/board.h>
@@ -45,7 +48,7 @@
 static u32 offset_32k __read_mostly;
 
 #ifdef CONFIG_ARCH_OMAP16XX
-static cycle_t omap16xx_32k_read(struct clocksource *cs)
+static cycle_t notrace omap16xx_32k_read(struct clocksource *cs)
 {
        return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
 }
@@ -54,7 +57,7 @@ static cycle_t omap16xx_32k_read(struct clocksource *cs)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2420
-static cycle_t omap2420_32k_read(struct clocksource *cs)
+static cycle_t notrace omap2420_32k_read(struct clocksource *cs)
 {
        return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
 }
@@ -63,7 +66,7 @@ static cycle_t omap2420_32k_read(struct clocksource *cs)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP2430
-static cycle_t omap2430_32k_read(struct clocksource *cs)
+static cycle_t notrace omap2430_32k_read(struct clocksource *cs)
 {
        return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
 }
@@ -72,7 +75,7 @@ static cycle_t omap2430_32k_read(struct clocksource *cs)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP3
-static cycle_t omap34xx_32k_read(struct clocksource *cs)
+static cycle_t notrace omap34xx_32k_read(struct clocksource *cs)
 {
        return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
 }
@@ -81,7 +84,7 @@ static cycle_t omap34xx_32k_read(struct clocksource *cs)
 #endif
 
 #ifdef CONFIG_ARCH_OMAP4
-static cycle_t omap44xx_32k_read(struct clocksource *cs)
+static cycle_t notrace omap44xx_32k_read(struct clocksource *cs)
 {
        return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
 }
@@ -93,7 +96,7 @@ static cycle_t omap44xx_32k_read(struct clocksource *cs)
  * Kernel assumes that sched_clock can be called early but may not have
  * things ready yet.
  */
-static cycle_t omap_32k_read_dummy(struct clocksource *cs)
+static cycle_t notrace omap_32k_read_dummy(struct clocksource *cs)
 {
        return 0;
 }
@@ -103,7 +106,6 @@ static struct clocksource clocksource_32k = {
        .rating         = 250,
        .read           = omap_32k_read_dummy,
        .mask           = CLOCKSOURCE_MASK(32),
-       .shift          = 10,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -111,10 +113,25 @@ static struct clocksource clocksource_32k = {
  * Returns current time from boot in nsecs. It's OK for this to wrap
  * around for now, as it's just a relative time stamp.
  */
-unsigned long long sched_clock(void)
+static DEFINE_CLOCK_DATA(cd);
+
+/*
+ * Constants generated by clocks_calc_mult_shift(m, s, 32768, NSEC_PER_SEC, 60).
+ * This gives a resolution of about 30us and a wrap period of about 36hrs.
+ */
+#define SC_MULT                4000000000u
+#define SC_SHIFT       17
+
+unsigned long long notrace sched_clock(void)
+{
+       u32 cyc = clocksource_32k.read(&clocksource_32k);
+       return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
+}
+
+static void notrace omap_update_sched_clock(void)
 {
-       return clocksource_cyc2ns(clocksource_32k.read(&clocksource_32k),
-                                 clocksource_32k.mult, clocksource_32k.shift);
+       u32 cyc = clocksource_32k.read(&clocksource_32k);
+       update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 /**
@@ -168,13 +185,13 @@ static int __init omap_init_clocksource_32k(void)
                if (!IS_ERR(sync_32k_ick))
                        clk_enable(sync_32k_ick);
 
-               clocksource_32k.mult = clocksource_hz2mult(32768,
-                                           clocksource_32k.shift);
-
                offset_32k = clocksource_32k.read(&clocksource_32k);
 
-               if (clocksource_register(&clocksource_32k))
+               if (clocksource_register_hz(&clocksource_32k, 32768))
                        printk(err, clocksource_32k.name);
+
+               init_fixed_sched_clock(&cd, omap_update_sched_clock, 32,
+                                      32768, SC_MULT, SC_SHIFT);
        }
        return 0;
 }
index bb937f3fabed3b9f88b9cb98df6109748d3d312b..4b2028ab4d2b5ca0047297ac7532be2add5a4002 100644 (file)
@@ -8,7 +8,7 @@
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
 #define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_CLKDEV_OMAP_H
 
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 
 struct omap_clk {
        u16                             cpu;
index 128b549c2796012bf0079ac94a1795423cd233eb..204865f91d93c469c609dcd15aafb6f1a7816334 100644 (file)
@@ -294,8 +294,8 @@ static inline void omap44xx_map_common_io(void)
 extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0,
                                 struct omap_sdrc_params *sdrc_cs1);
 
-#define __arch_ioremap(p,s,t)  omap_ioremap(p,s,t)
-#define __arch_iounmap(v)      omap_iounmap(v)
+#define __arch_ioremap omap_ioremap
+#define __arch_iounmap omap_iounmap
 
 void __iomem *omap_ioremap(unsigned long phys, size_t size, unsigned int type);
 void omap_iounmap(volatile void __iomem *addr);
index d5306bee44b2fe74cad97f3e459fc579a0b4d6fa..f8d922fb5584e1763b1ddecd8644523533295d2d 100644 (file)
 #define lbus_to_virt(x)                ((x) - OMAP1510_LB_OFFSET + PAGE_OFFSET)
 #define is_lbus_device(dev)    (cpu_is_omap15xx() && dev && (strncmp(dev_name(dev), "ohci", 4) == 0))
 
-#define __arch_page_to_dma(dev, page)  \
-       ({ dma_addr_t __dma = page_to_phys(page); \
+#define __arch_pfn_to_dma(dev, pfn)    \
+       ({ dma_addr_t __dma = __pfn_to_phys(pfn); \
           if (is_lbus_device(dev)) \
                __dma = __dma - PHYS_OFFSET + OMAP1510_LB_OFFSET; \
           __dma; })
 
-#define __arch_dma_to_page(dev, addr)  \
+#define __arch_dma_to_pfn(dev, addr)   \
        ({ dma_addr_t __dma = addr;                             \
           if (is_lbus_device(dev))                             \
                __dma += PHYS_OFFSET - OMAP1510_LB_OFFSET;      \
-          phys_to_page(__dma);                                 \
+          __phys_to_pfn(__dma);                                \
        })
 
 #define __arch_dma_to_virt(dev, addr)  ({ (void *) (is_lbus_device(dev) ? \
index ecd6a488c497c28fda8aea2c3412a95b67e05cc7..7a10257909efa02969d61c5572bbacf9752adc84 100644 (file)
@@ -18,7 +18,6 @@
 #define OMAP_ARCH_SMP_H
 
 #include <asm/hardware/gic.h>
-#include <asm/smp_mpidr.h>
 
 /* Needed for secondary core boot */
 extern void omap_secondary_startup(void);
@@ -29,9 +28,9 @@ extern u32 omap_read_auxcoreboot0(void);
 /*
  * We use Soft IRQ1 as the IPI
  */
-static inline void smp_cross_call(const struct cpumask *mask)
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
 {
-       gic_raise_softirq(mask, 1);
+       gic_raise_softirq(mask, ipi);
 }
 
 #endif
index 715a30177f2857c02ed227e74240359be58dbb1a..c3da2478b2aa0d29ac605606d095733843566c03 100644 (file)
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/cnt32_to_63.h>
 #include <linux/timer.h>
 #include <linux/clockchips.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <asm/sched_clock.h>
 #include <asm/mach/time.h>
 #include <mach/bridge-regs.h>
 #include <mach/hardware.h>
@@ -44,52 +44,26 @@ static u32 ticks_per_jiffy;
 
 /*
  * Orion's sched_clock implementation. It has a resolution of
- * at least 7.5ns (133MHz TCLK) and a maximum value of 834 days.
- *
- * Because the hardware timer period is quite short (21 secs if
- * 200MHz TCLK) and because cnt32_to_63() needs to be called at
- * least once per half period to work properly, a kernel timer is
- * set up to ensure this requirement is always met.
+ * at least 7.5ns (133MHz TCLK).
  */
-#define TCLK2NS_SCALE_FACTOR 8
-
-static unsigned long tclk2ns_scale;
+static DEFINE_CLOCK_DATA(cd);
 
-unsigned long long sched_clock(void)
+unsigned long long notrace sched_clock(void)
 {
-       unsigned long long v = cnt32_to_63(0xffffffff - readl(TIMER0_VAL));
-       return (v * tclk2ns_scale) >> TCLK2NS_SCALE_FACTOR;
+       u32 cyc = 0xffffffff - readl(TIMER0_VAL);
+       return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
-static struct timer_list cnt32_to_63_keepwarm_timer;
 
-static void cnt32_to_63_keepwarm(unsigned long data)
+static void notrace orion_update_sched_clock(void)
 {
-       mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
-       (void) sched_clock();
+       u32 cyc = 0xffffffff - readl(TIMER0_VAL);
+       update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static void __init setup_sched_clock(unsigned long tclk)
 {
-       unsigned long long v;
-       unsigned long data;
-
-       v = NSEC_PER_SEC;
-       v <<= TCLK2NS_SCALE_FACTOR;
-       v += tclk/2;
-       do_div(v, tclk);
-       /*
-        * We want an even value to automatically clear the top bit
-        * returned by cnt32_to_63() without an additional run time
-        * instruction. So if the LSB is 1 then round it up.
-        */
-       if (v & 1)
-               v++;
-       tclk2ns_scale = v;
-
-       data = (0xffffffffUL / tclk / 2 - 2) * HZ;
-       setup_timer(&cnt32_to_63_keepwarm_timer, cnt32_to_63_keepwarm, data);
-       mod_timer(&cnt32_to_63_keepwarm_timer, round_jiffies(jiffies + data));
+       init_sched_clock(&cd, orion_update_sched_clock, 32, tclk);
 }
 
 /*
@@ -102,7 +76,6 @@ static cycle_t orion_clksrc_read(struct clocksource *cs)
 
 static struct clocksource orion_clksrc = {
        .name           = "orion_clocksource",
-       .shift          = 20,
        .rating         = 300,
        .read           = orion_clksrc_read,
        .mask           = CLOCKSOURCE_MASK(32),
@@ -245,8 +218,7 @@ void __init orion_time_init(unsigned int irq, unsigned int tclk)
        writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
        u = readl(TIMER_CTRL);
        writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
-       orion_clksrc.mult = clocksource_hz2mult(tclk, orion_clksrc.shift);
-       clocksource_register(&orion_clksrc);
+       clocksource_register_hz(&orion_clksrc, tclk);
 
        /*
         * Setup clockevent timer (interrupt-driven.)
index 5a27b1b538f2885eab6cd6ccdfd670834607f665..eb105e61c746750f716cb0f8d392da560f8f1332 100644 (file)
@@ -8,7 +8,7 @@ config PLAT_S3C24XX
        default y
        select NO_IOPORT
        select ARCH_REQUIRE_GPIOLIB
-       select S3C_DEVICE_NAND
+       select S3C_DEV_NAND
        select S3C_GPIO_CFG_S3C24XX
        help
          Base platform code for any Samsung S3C24XX device
index 298bafc0a52f71d4edfa91fca8c146204329216e..2572260f990f1494f98fff245d338a8dae15ad0b 100644 (file)
@@ -15,7 +15,7 @@
 #define __PLAT_CLOCK_H
 
 #include <linux/list.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <linux/types.h>
 
 /* clk structure flags */
index ab211652e4ca79d3e814bc9967cdace8d10edf7c..839c88df99947d87ed825ba69a00323c4956cd8a 100644 (file)
@@ -81,8 +81,6 @@ static struct clocksource clksrc = {
        .rating = 200,          /* its a pretty decent clock */
        .read = clocksource_read_cycles,
        .mask = 0xFFFF,         /* 16 bits */
-       .mult = 0,              /* to be computed */
-       .shift = 0,             /* to be computed */
        .flags = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -105,10 +103,8 @@ static void spear_clocksource_init(void)
        val |= CTRL_ENABLE ;
        writew(val, gpt_base + CR(CLKSRC));
 
-       clocksource_calc_mult_shift(&clksrc, tick_rate, SPEAR_MIN_RANGE);
-
        /* register the clocksource */
-       clocksource_register(&clksrc);
+       clocksource_register_hz(&clksrc, tick_rate);
 }
 
 static struct clock_event_device clkevt = {
index e593a2a801c63370efea993d529adf8b8960e0f4..2e712e17ce7257757c4592587ce63b296e39f995 100644 (file)
@@ -25,9 +25,9 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
-#include <asm/clkdev.h>
 #include <mach/platform.h>
 #include <mach/regs-clkctrl.h>
 
index 063c7bc0e740baf52dc6e345347d1241f3b431f7..c395630a6edcba2efb676f6f1b209189953a863c 100644 (file)
@@ -89,7 +89,6 @@ static struct clocksource cksrc_stmp3xxx = {
        .rating         = 250,
        .read           = stmp3xxx_clock_read,
        .mask           = CLOCKSOURCE_MASK(16),
-       .shift          = 10,
        .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -106,8 +105,6 @@ static struct irqaction stmp3xxx_timer_irq = {
  */
 static void __init stmp3xxx_init_timer(void)
 {
-       cksrc_stmp3xxx.mult = clocksource_hz2mult(CLOCK_TICK_RATE,
-                               cksrc_stmp3xxx.shift);
        ckevt_timrot.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
                                ckevt_timrot.shift);
        ckevt_timrot.min_delta_ns = clockevent_delta2ns(2, &ckevt_timrot);
@@ -140,7 +137,7 @@ static void __init stmp3xxx_init_timer(void)
 
        setup_irq(IRQ_TIMER0, &stmp3xxx_timer_irq);
 
-       clocksource_register(&cksrc_stmp3xxx);
+       clocksource_register_hz(&cksrc_stmp3xxx, CLOCK_TICK_RATE);
        clockevents_register_device(&ckevt_timrot);
 }
 
index 5cf88e8427b15e66aafa287f1960e937a26fb89a..16dde08199349b4a004ab58746f43d40d0d88424 100644 (file)
@@ -1,7 +1,7 @@
 obj-y  := clock.o
-obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
-obj-$(CONFIG_ARCH_REALVIEW) += sched-clock.o
-obj-$(CONFIG_ARCH_VERSATILE) += sched-clock.o
+ifneq ($(CONFIG_ARCH_INTEGRATOR),y)
+obj- += sched-clock.o
+endif
 ifeq ($(CONFIG_LEDS_CLASS),y)
 obj-$(CONFIG_ARCH_REALVIEW) += leds.o
 obj-$(CONFIG_ARCH_VERSATILE) += leds.o
diff --git a/arch/arm/plat-versatile/include/plat/sched_clock.h b/arch/arm/plat-versatile/include/plat/sched_clock.h
new file mode 100644 (file)
index 0000000..5c3e4fc
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef ARM_PLAT_SCHED_CLOCK_H
+#define ARM_PLAT_SCHED_CLOCK_H
+
+void versatile_sched_clock_init(void __iomem *, unsigned long);
+
+#endif
index 9696ddc238c9aa159de79e377e28bcaf326c0b32..3d6a4c292cab904badbf06be1075c2d709ce1413 100644 (file)
  * 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/cnt32_to_63.h>
 #include <linux/io.h>
 #include <linux/sched.h>
-#include <asm/div64.h>
 
-#include <mach/hardware.h>
-#include <mach/platform.h>
+#include <asm/sched_clock.h>
+#include <plat/sched_clock.h>
 
-#ifdef VERSATILE_SYS_BASE
-#define REFCOUNTER     (__io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_24MHz_OFFSET)
-#endif
-
-#ifdef REALVIEW_SYS_BASE
-#define REFCOUNTER     (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_24MHz_OFFSET)
-#endif
+static DEFINE_CLOCK_DATA(cd);
+static void __iomem *ctr;
 
 /*
- * This is the Realview and Versatile sched_clock implementation.  This
- * has a resolution of 41.7ns, and a maximum value of about 35583 days.
- *
- * The return value is guaranteed to be monotonic in that range as
- * long as there is always less than 89 seconds between successive
- * calls to this function.
+ * Constants generated by clocks_calc_mult_shift(m, s, 24MHz, NSEC_PER_SEC, 60).
+ * This gives a resolution of about 41ns and a wrap period of about 178s.
  */
-unsigned long long sched_clock(void)
+#define SC_MULT                2796202667u
+#define SC_SHIFT       26
+
+unsigned long long notrace sched_clock(void)
 {
-       unsigned long long v = cnt32_to_63(readl(REFCOUNTER));
+       if (ctr) {
+               u32 cyc = readl(ctr);
+               return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0,
+                                               SC_MULT, SC_SHIFT);
+       } else
+               return 0;
+}
 
-       /* the <<1 gets rid of the cnt_32_to_63 top bit saving on a bic insn */
-       v *= 125<<1;
-       do_div(v, 3<<1);
+static void notrace versatile_update_sched_clock(void)
+{
+       u32 cyc = readl(ctr);
+       update_sched_clock(&cd, cyc, (u32)~0);
+}
 
-       return v;
+void __init versatile_sched_clock_init(void __iomem *reg, unsigned long rate)
+{
+       ctr = reg;
+       init_fixed_sched_clock(&cd, versatile_update_sched_clock,
+                              32, rate, SC_MULT, SC_SHIFT);
 }
index 8063a322c790dd80b3c6b0719541d9e937c2a2bc..0797cb528b46339113c355dcc416c6e241e95dd5 100644 (file)
  */
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/cpu.h>
 #include <linux/kernel.h>
+#include <linux/notifier.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <linux/init.h>
 
 #include <asm/cputype.h>
@@ -484,7 +487,24 @@ void vfp_flush_hwstate(struct thread_info *thread)
        put_cpu();
 }
 
-#include <linux/smp.h>
+/*
+ * VFP hardware can lose all context when a CPU goes offline.
+ * Safely clear our held state when a CPU has been killed, and
+ * re-enable access to VFP when the CPU comes back online.
+ *
+ * Both CPU_DYING and CPU_STARTING are called on the CPU which
+ * is being offlined/onlined.
+ */
+static int vfp_hotplug(struct notifier_block *b, unsigned long action,
+       void *hcpu)
+{
+       if (action == CPU_DYING || action == CPU_DYING_FROZEN) {
+               unsigned int cpu = (long)hcpu;
+               last_VFP_context[cpu] = NULL;
+       } else if (action == CPU_STARTING || action == CPU_STARTING_FROZEN)
+               vfp_enable(NULL);
+       return NOTIFY_OK;
+}
 
 /*
  * VFP support code initialisation.
@@ -514,6 +534,8 @@ static int __init vfp_init(void)
        else if (vfpsid & FPSID_NODOUBLE) {
                printk("no double precision support\n");
        } else {
+               hotcpu_notifier(vfp_hotplug, 0);
+
                smp_call_function(vfp_enable, NULL, 1);
 
                VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT;  /* Extract the architecture version */
index 67a2fa2caa494ff06e2550aa8cea7cf61d69f39e..0a9b5b8b2a1935103ecf9d81a2367d0a0633f1e4 100644 (file)
@@ -19,6 +19,8 @@ config MIPS
        select GENERIC_ATOMIC64 if !64BIT
        select HAVE_DMA_ATTRS
        select HAVE_DMA_API_DEBUG
+       select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_PROBE
 
 menu "Machine selection"
 
@@ -1664,6 +1666,28 @@ config PAGE_SIZE_64KB
 
 endchoice
 
+config FORCE_MAX_ZONEORDER
+       int "Maximum zone order"
+       range 13 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB
+       default "13" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_32KB
+       range 12 64 if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB
+       default "12" if SYS_SUPPORTS_HUGETLBFS && PAGE_SIZE_16KB
+       range 11 64
+       default "11"
+       help
+         The kernel memory allocator divides physically contiguous memory
+         blocks into "zones", where each zone is a power of two number of
+         pages.  This option selects the largest power of two that the kernel
+         keeps in the memory allocator.  If you need to allocate very large
+         blocks of physically contiguous memory, then you may need to
+         increase this value.
+
+         This config option is actually maximum order plus one. For example,
+         a value of 11 means that the largest free memory block is 2^10 pages.
+
+         The page size is not necessarily 4KB.  Keep this in mind
+         when choosing a value for this option.
+
 config BOARD_SCACHE
        bool
 
@@ -1921,20 +1945,6 @@ config CPU_R4000_WORKAROUNDS
 config CPU_R4400_WORKAROUNDS
        bool
 
-#
-# Use the generic interrupt handling code in kernel/irq/:
-#
-config GENERIC_HARDIRQS
-       bool
-       default y
-
-config GENERIC_IRQ_PROBE
-       bool
-       default y
-
-config IRQ_PER_CPU
-       bool
-
 #
 # - Highmem only makes sense for the 32-bit kernel.
 # - The current highmem code will only work properly on physically indexed
index 3691630931d6100ae901d8adbddcc6ccb6cf960e..9e7814db3d03411d08bfe93868f84d646dd93d93 100644 (file)
@@ -27,6 +27,7 @@
 static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                            unsigned int old_state)
 {
+#ifdef CONFIG_SERIAL_8250
        switch (state) {
        case 0:
                if ((__raw_readl(port->membase + UART_MOD_CNTRL) & 3) != 3) {
@@ -49,6 +50,7 @@ static void alchemy_8250_pm(struct uart_port *port, unsigned int state,
                serial8250_do_pm(port, state, old_state);
                break;
        }
+#endif
 }
 
 #define PORT(_base, _irq)                                      \
index b30df5c97ad35e46e534b047c144975c01db6b76..baeb21385058b8d5efe5e046620e66746b754d73 100644 (file)
@@ -54,10 +54,9 @@ void __init prom_init(void)
 
        prom_init_cmdline();
        memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
+       if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))
                memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
-       else
-               strict_strtoul(memsize_str, 0, &memsize);
+
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
index fc0e7154e8d69835c56eb45891a9e98beca0e82f..2ca4ada1c291cf7cb13f0ac047d6b879e9e1b400 100644 (file)
@@ -239,12 +239,12 @@ static void tnetd7300_set_clock(u32 shift, struct tnetd7300_clock *clock,
        calculate(base_clock, frequency, &prediv, &postdiv, &mul);
 
        writel(((prediv - 1) << PREDIV_SHIFT) | (postdiv - 1), &clock->ctrl);
-       msleep(1);
+       mdelay(1);
        writel(4, &clock->pll);
        while (readl(&clock->pll) & PLL_STATUS)
                ;
        writel(((mul - 1) << MUL_SHIFT) | (0xff << 3) | 0x0e, &clock->pll);
-       msleep(75);
+       mdelay(75);
 }
 
 static void __init tnetd7300_init_clocks(void)
@@ -456,7 +456,7 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_put);
 
-int __init ar7_init_clocks(void)
+void __init ar7_init_clocks(void)
 {
        switch (ar7_chip_id()) {
        case AR7_CHIP_7100:
@@ -472,7 +472,4 @@ int __init ar7_init_clocks(void)
        }
        /* adjust vbus clock rate */
        vbus_clk.rate = bus_clk.rate / 2;
-
-       return 0;
 }
-arch_initcall(ar7_init_clocks);
index 5fb8a01340855f402340914784c65924faaa163e..22c93213b233db0090a2c8175cee864f2cf62619 100644 (file)
@@ -30,6 +30,9 @@ void __init plat_time_init(void)
 {
        struct clk *cpu_clk;
 
+       /* Initialize ar7 clocks so the CPU clock frequency is correct */
+       ar7_init_clocks();
+
        cpu_clk = clk_get(NULL, "cpu");
        if (IS_ERR(cpu_clk)) {
                printk(KERN_ERR "unable to get cpu clock\n");
index b1aee33efd11454e7f47c7d8beb7d0d50ed9ca2a..c95f90bf734ca9c1765b14728f391a14af62917b 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/reboot.h>
 #include <asm/time.h>
 #include <bcm47xx.h>
-#include <asm/fw/cfe/cfe_api.h>
 #include <asm/mach-bcm47xx/nvram.h>
 
 struct ssb_bus ssb_bcm47xx;
@@ -57,68 +56,112 @@ static void bcm47xx_machine_halt(void)
                cpu_relax();
 }
 
-static void str2eaddr(char *str, char *dest)
-{
-       int i = 0;
+#define READ_FROM_NVRAM(_outvar, name, buf) \
+       if (nvram_getenv(name, buf, sizeof(buf)) >= 0)\
+               sprom->_outvar = simple_strtoul(buf, NULL, 0);
 
-       if (str == NULL) {
-               memset(dest, 0, 6);
-               return;
+static void bcm47xx_fill_sprom(struct ssb_sprom *sprom)
+{
+       char buf[100];
+       u32 boardflags;
+
+       memset(sprom, 0, sizeof(struct ssb_sprom));
+
+       sprom->revision = 1; /* Fallback: Old hardware does not define this. */
+       READ_FROM_NVRAM(revision, "sromrev", buf);
+       if (nvram_getenv("il0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->il0mac);
+       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et0mac);
+       if (nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
+               nvram_parse_macaddr(buf, sprom->et1mac);
+       READ_FROM_NVRAM(et0phyaddr, "et0phyaddr", buf);
+       READ_FROM_NVRAM(et1phyaddr, "et1phyaddr", buf);
+       READ_FROM_NVRAM(et0mdcport, "et0mdcport", buf);
+       READ_FROM_NVRAM(et1mdcport, "et1mdcport", buf);
+       READ_FROM_NVRAM(board_rev, "boardrev", buf);
+       READ_FROM_NVRAM(country_code, "ccode", buf);
+       READ_FROM_NVRAM(ant_available_a, "aa5g", buf);
+       READ_FROM_NVRAM(ant_available_bg, "aa2g", buf);
+       READ_FROM_NVRAM(pa0b0, "pa0b0", buf);
+       READ_FROM_NVRAM(pa0b1, "pa0b1", buf);
+       READ_FROM_NVRAM(pa0b2, "pa0b2", buf);
+       READ_FROM_NVRAM(pa1b0, "pa1b0", buf);
+       READ_FROM_NVRAM(pa1b1, "pa1b1", buf);
+       READ_FROM_NVRAM(pa1b2, "pa1b2", buf);
+       READ_FROM_NVRAM(pa1lob0, "pa1lob0", buf);
+       READ_FROM_NVRAM(pa1lob2, "pa1lob1", buf);
+       READ_FROM_NVRAM(pa1lob1, "pa1lob2", buf);
+       READ_FROM_NVRAM(pa1hib0, "pa1hib0", buf);
+       READ_FROM_NVRAM(pa1hib2, "pa1hib1", buf);
+       READ_FROM_NVRAM(pa1hib1, "pa1hib2", buf);
+       READ_FROM_NVRAM(gpio0, "wl0gpio0", buf);
+       READ_FROM_NVRAM(gpio1, "wl0gpio1", buf);
+       READ_FROM_NVRAM(gpio2, "wl0gpio2", buf);
+       READ_FROM_NVRAM(gpio3, "wl0gpio3", buf);
+       READ_FROM_NVRAM(maxpwr_bg, "pa0maxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_al, "pa1lomaxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_a, "pa1maxpwr", buf);
+       READ_FROM_NVRAM(maxpwr_ah, "pa1himaxpwr", buf);
+       READ_FROM_NVRAM(itssi_a, "pa1itssit", buf);
+       READ_FROM_NVRAM(itssi_bg, "pa0itssit", buf);
+       READ_FROM_NVRAM(tri2g, "tri2g", buf);
+       READ_FROM_NVRAM(tri5gl, "tri5gl", buf);
+       READ_FROM_NVRAM(tri5g, "tri5g", buf);
+       READ_FROM_NVRAM(tri5gh, "tri5gh", buf);
+       READ_FROM_NVRAM(rxpo2g, "rxpo2g", buf);
+       READ_FROM_NVRAM(rxpo5g, "rxpo5g", buf);
+       READ_FROM_NVRAM(rssisav2g, "rssisav2g", buf);
+       READ_FROM_NVRAM(rssismc2g, "rssismc2g", buf);
+       READ_FROM_NVRAM(rssismf2g, "rssismf2g", buf);
+       READ_FROM_NVRAM(bxa2g, "bxa2g", buf);
+       READ_FROM_NVRAM(rssisav5g, "rssisav5g", buf);
+       READ_FROM_NVRAM(rssismc5g, "rssismc5g", buf);
+       READ_FROM_NVRAM(rssismf5g, "rssismf5g", buf);
+       READ_FROM_NVRAM(bxa5g, "bxa5g", buf);
+       READ_FROM_NVRAM(cck2gpo, "cck2gpo", buf);
+       READ_FROM_NVRAM(ofdm2gpo, "ofdm2gpo", buf);
+       READ_FROM_NVRAM(ofdm5glpo, "ofdm5glpo", buf);
+       READ_FROM_NVRAM(ofdm5gpo, "ofdm5gpo", buf);
+       READ_FROM_NVRAM(ofdm5ghpo, "ofdm5ghpo", buf);
+
+       if (nvram_getenv("boardflags", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
        }
-
-       for (;;) {
-               dest[i++] = (char) simple_strtoul(str, NULL, 16);
-               str += 2;
-               if (!*str++ || i == 6)
-                       break;
+       if (nvram_getenv("boardflags2", buf, sizeof(buf)) >= 0) {
+               boardflags = simple_strtoul(buf, NULL, 0);
+               if (boardflags) {
+                       sprom->boardflags2_lo = (boardflags & 0x0000FFFFU);
+                       sprom->boardflags2_hi = (boardflags & 0xFFFF0000U) >> 16;
+               }
        }
 }
 
 static int bcm47xx_get_invariants(struct ssb_bus *bus,
                                   struct ssb_init_invariants *iv)
 {
-       char buf[100];
+       char buf[20];
 
        /* Fill boardinfo structure */
        memset(&(iv->boardinfo), 0 , sizeof(struct ssb_boardinfo));
 
-       if (cfe_getenv("boardvendor", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
-               iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-       if (cfe_getenv("boardtype", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
+       if (nvram_getenv("boardvendor", buf, sizeof(buf)) >= 0)
+               iv->boardinfo.vendor = (u16)simple_strtoul(buf, NULL, 0);
+       else
+               iv->boardinfo.vendor = SSB_BOARDVENDOR_BCM;
+       if (nvram_getenv("boardtype", buf, sizeof(buf)) >= 0)
                iv->boardinfo.type = (u16)simple_strtoul(buf, NULL, 0);
-       if (cfe_getenv("boardrev", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
+       if (nvram_getenv("boardrev", buf, sizeof(buf)) >= 0)
                iv->boardinfo.rev = (u16)simple_strtoul(buf, NULL, 0);
 
-       /* Fill sprom structure */
-       memset(&(iv->sprom), 0, sizeof(struct ssb_sprom));
-       iv->sprom.revision = 3;
-
-       if (cfe_getenv("et0macaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0macaddr", buf, sizeof(buf)) >= 0)
-               str2eaddr(buf, iv->sprom.et0mac);
+       bcm47xx_fill_sprom(&iv->sprom);
 
-       if (cfe_getenv("et1macaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1macaddr", buf, sizeof(buf)) >= 0)
-               str2eaddr(buf, iv->sprom.et1mac);
-
-       if (cfe_getenv("et0phyaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0phyaddr", buf, sizeof(buf)) >= 0)
-               iv->sprom.et0phyaddr = simple_strtoul(buf, NULL, 0);
-
-       if (cfe_getenv("et1phyaddr", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1phyaddr", buf, sizeof(buf)) >= 0)
-               iv->sprom.et1phyaddr = simple_strtoul(buf, NULL, 0);
-
-       if (cfe_getenv("et0mdcport", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et0mdcport", buf, sizeof(buf)) >= 0)
-               iv->sprom.et0mdcport = simple_strtoul(buf, NULL, 10);
-
-       if (cfe_getenv("et1mdcport", buf, sizeof(buf)) >= 0 ||
-           nvram_getenv("et1mdcport", buf, sizeof(buf)) >= 0)
-               iv->sprom.et1mdcport = simple_strtoul(buf, NULL, 10);
+       if (nvram_getenv("cardbus", buf, sizeof(buf)) >= 0)
+               iv->has_cardbus_slot = !!simple_strtoul(buf, NULL, 10);
 
        return 0;
 }
@@ -126,12 +169,28 @@ static int bcm47xx_get_invariants(struct ssb_bus *bus,
 void __init plat_mem_setup(void)
 {
        int err;
+       char buf[100];
+       struct ssb_mipscore *mcore;
 
        err = ssb_bus_ssbbus_register(&ssb_bcm47xx, SSB_ENUM_BASE,
                                      bcm47xx_get_invariants);
        if (err)
                panic("Failed to initialize SSB bus (err %d)\n", err);
 
+       mcore = &ssb_bcm47xx.mipscore;
+       if (nvram_getenv("kernel_args", buf, sizeof(buf)) >= 0) {
+               if (strstr(buf, "console=ttyS1")) {
+                       struct ssb_serial_port port;
+
+                       printk(KERN_DEBUG "Swapping serial ports!\n");
+                       /* swap serial ports */
+                       memcpy(&port, &mcore->serial_ports[0], sizeof(port));
+                       memcpy(&mcore->serial_ports[0], &mcore->serial_ports[1],
+                              sizeof(port));
+                       memcpy(&mcore->serial_ports[1], &port, sizeof(port));
+               }
+       }
+
        _machine_restart = bcm47xx_machine_restart;
        _machine_halt = bcm47xx_machine_halt;
        pm_power_off = bcm47xx_machine_halt;
index 06d59dcbe24310a92669983231a51e3aad34d324..86877539c6e83679f248d7245324693a690105e6 100644 (file)
  * These are the PRID's for when 23:16 == PRID_COMP_BROADCOM
  */
 
-#define PRID_IMP_BMIPS4KC      0x4000
-#define PRID_IMP_BMIPS32       0x8000
+#define PRID_IMP_BMIPS32_REV4  0x4000
+#define PRID_IMP_BMIPS32_REV8  0x8000
 #define PRID_IMP_BMIPS3300     0x9000
 #define PRID_IMP_BMIPS3300_ALT 0x9100
 #define PRID_IMP_BMIPS3300_BUG 0x0000
index fd1d39eb74319b60473daf46cb5e4ecf1bcacb2e..455c0ac7d4ea84632cc41c40ee48e7dd9e82ce86 100644 (file)
@@ -249,7 +249,8 @@ extern struct mips_abi mips_abi_n32;
 
 #define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
-       set_personality(PER_LINUX);                                     \
+       if (personality(current->personality) != PER_LINUX)             \
+               set_personality(PER_LINUX);                             \
                                                                        \
        current->thread.abi = &mips_abi;                                \
 } while (0)
@@ -296,6 +297,8 @@ do {                                                                        \
 
 #define SET_PERSONALITY(ex)                                            \
 do {                                                                   \
+       unsigned int p;                                                 \
+                                                                       \
        clear_thread_flag(TIF_32BIT_REGS);                              \
        clear_thread_flag(TIF_32BIT_ADDR);                              \
                                                                        \
@@ -304,7 +307,8 @@ do {                                                                        \
        else                                                            \
                current->thread.abi = &mips_abi;                        \
                                                                        \
-       if (current->personality != PER_LINUX32)                        \
+       p = personality(current->personality);                          \
+       if (p != PER_LINUX32 && p != PER_LINUX)                         \
                set_personality(PER_LINUX);                             \
 } while (0)
 
index c98bf514ec7de9efe6596721cfa472d878da3f16..5b017f23e243d71b195cfea786c70ef389da7810 100644 (file)
@@ -329,10 +329,14 @@ static inline void pfx##write##bwlq(type val,                             \
                        "dsrl32 %L0, %L0, 0"                    "\n\t"  \
                        "dsll32 %M0, %M0, 0"                    "\n\t"  \
                        "or     %L0, %L0, %M0"                  "\n\t"  \
+                       ".set   push"                           "\n\t"  \
+                       ".set   noreorder"                      "\n\t"  \
+                       ".set   nomacro"                        "\n\t"  \
                        "sd     %L0, %2"                        "\n\t"  \
+                       ".set   pop"                            "\n\t"  \
                        ".set   mips0"                          "\n"    \
                        : "=r" (__tmp)                                  \
-                       : "0" (__val), "m" (*__mem));                   \
+                       : "0" (__val), "R" (*__mem));                   \
                if (irq)                                                \
                        local_irq_restore(__flags);                     \
        } else                                                          \
@@ -355,12 +359,16 @@ static inline type pfx##read##bwlq(const volatile void __iomem *mem)      \
                        local_irq_save(__flags);                        \
                __asm__ __volatile__(                                   \
                        ".set   mips3"          "\t\t# __readq" "\n\t"  \
+                       ".set   push"                           "\n\t"  \
+                       ".set   noreorder"                      "\n\t"  \
+                       ".set   nomacro"                        "\n\t"  \
                        "ld     %L0, %1"                        "\n\t"  \
+                       ".set   pop"                            "\n\t"  \
                        "dsra32 %M0, %L0, 0"                    "\n\t"  \
                        "sll    %L0, %L0, 0"                    "\n\t"  \
                        ".set   mips0"                          "\n"    \
                        : "=r" (__val)                                  \
-                       : "m" (*__mem));                                \
+                       : "R" (*__mem));                                \
                if (irq)                                                \
                        local_irq_restore(__flags);                     \
        } else {                                                        \
index 7919d76186bf1b78dca75c62e1fc41f731fc6ebb..07d3fadb24437e289bae5c8da747b2fdd647e8a5 100644 (file)
@@ -201,7 +201,6 @@ static inline void ar7_device_off(u32 bit)
 }
 
 int __init ar7_gpio_init(void);
-
-int __init ar7_gpio_init(void);
+void __init ar7_init_clocks(void);
 
 #endif /* __AR7_H__ */
index c58ebd8bc1551dd92e14111acc1ac92c4b17d1b7..9759588ba3cff0c81da6cd454148a6787e4babcf 100644 (file)
@@ -12,6 +12,7 @@
 #define __NVRAM_H
 
 #include <linux/types.h>
+#include <linux/kernel.h>
 
 struct nvram_header {
        u32 magic;
@@ -36,4 +37,10 @@ struct nvram_header {
 
 extern int nvram_getenv(char *name, char *val, size_t val_len);
 
+static inline void nvram_parse_macaddr(char *buf, u8 *macaddr)
+{
+       sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &macaddr[0], &macaddr[1],
+              &macaddr[2], &macaddr[3], &macaddr[4], &macaddr[5]);
+}
+
 #endif
index 5742bb4d78f4db6aefa966b443dee7e095a2cfc5..5c0a3575877cce27c171d2d9a676dd8cf8073a7a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 2009 Qi Hardware inc.,
  * Author: Xiangfu Liu <xiangfu@qi-hardware.com>
- * Copyright 2010, Lars-Petrer Clausen <lars@metafoo.de>
+ * Copyright 2010, Lars-Peter Clausen <lars@metafoo.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 or later
@@ -235,7 +235,7 @@ static const unsigned int qi_lb60_keypad_rows[] = {
        QI_LB60_GPIO_KEYIN(3),
        QI_LB60_GPIO_KEYIN(4),
        QI_LB60_GPIO_KEYIN(5),
-       QI_LB60_GPIO_KEYIN(7),
+       QI_LB60_GPIO_KEYIN(6),
        QI_LB60_GPIO_KEYIN8,
 };
 
index 95bc2b5b14f1b2c56cd141f2c8a2b8ea6370dcde..1cc9e544d16bd16609aaef30bd5779ad26f5dc14 100644 (file)
@@ -208,7 +208,7 @@ struct platform_device jz4740_i2s_device = {
 
 /* PCM */
 struct platform_device jz4740_pcm_device = {
-       .name           = "jz4740-pcm",
+       .name           = "jz4740-pcm-audio",
        .id             = -1,
 };
 
index cfeac15eb2e4d5716530fd07c5b6db3a8d77cadb..4a70407f55bb7df9d68bc46256b8c007c08c6e59 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/bootinfo.h>
 #include <asm/mach-jz4740/base.h>
 
-void jz4740_init_cmdline(int argc, char *argv[])
+static __init void jz4740_init_cmdline(int argc, char *argv[])
 {
        unsigned int count = COMMAND_LINE_SIZE - 1;
        int i;
index 2f4d7a99bcc2fcc91b3838599b0b0c3d4fb1c432..98c5a9737c14d2c200a161640122f9a8af053e88 100644 (file)
@@ -32,7 +32,7 @@ static int mips_next_event(unsigned long delta,
        cnt = read_c0_count();
        cnt += delta;
        write_c0_compare(cnt);
-       res = ((int)(read_c0_count() - cnt) > 0) ? -ETIME : 0;
+       res = ((int)(read_c0_count() - cnt) >= 0) ? -ETIME : 0;
        return res;
 }
 
index 71620e19827ad681a7834f0e400104cec4968ef2..68dae7b6b5db62a0a48a17e6fe339a2d56bd8bd8 100644 (file)
@@ -905,7 +905,8 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
 {
        decode_configs(c);
        switch (c->processor_id & 0xff00) {
-       case PRID_IMP_BMIPS32:
+       case PRID_IMP_BMIPS32_REV4:
+       case PRID_IMP_BMIPS32_REV8:
                c->cputype = CPU_BMIPS32;
                __cpu_name[cpu] = "Broadcom BMIPS32";
                break;
@@ -933,10 +934,6 @@ static inline void cpu_probe_broadcom(struct cpuinfo_mips *c, unsigned int cpu)
                __cpu_name[cpu] = "Broadcom BMIPS5000";
                c->options |= MIPS_CPU_ULRI;
                break;
-       case PRID_IMP_BMIPS4KC:
-               c->cputype = CPU_4KC;
-               __cpu_name[cpu] = "MIPS 4Kc";
-               break;
        }
 }
 
index 6343b4a5b8350cb3a93edea5d75f3154cde48343..876a75cc376f7a8602d231c1c11440be8c88d7ae 100644 (file)
@@ -251,14 +251,15 @@ SYSCALL_DEFINE5(n32_msgrcv, int, msqid, u32, msgp, size_t, msgsz,
 
 SYSCALL_DEFINE1(32_personality, unsigned long, personality)
 {
+       unsigned int p = personality & 0xffffffff;
        int ret;
-       personality &= 0xffffffff;
+
        if (personality(current->personality) == PER_LINUX32 &&
-           personality == PER_LINUX)
-               personality = PER_LINUX32;
-       ret = sys_personality(personality);
-       if (ret == PER_LINUX32)
-               ret = PER_LINUX;
+           personality(p) == PER_LINUX)
+               p = (p & ~PER_MASK) | PER_LINUX32;
+       ret = sys_personality(p);
+       if (ret != -1 && personality(ret) == PER_LINUX32)
+               ret = (ret & ~PER_MASK) | PER_LINUX;
        return ret;
 }
 
index 99960940d4a410bba1e9842a7049161e74d04d25..ae167df73dddf2df41a2158050c164cb4fb346d4 100644 (file)
@@ -142,7 +142,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        childregs->regs[7] = 0; /* Clear error flag */
 
        childregs->regs[2] = 0; /* Child gets zero as return value */
-       regs->regs[2] = p->pid;
 
        if (childregs->cp0_status & ST0_CU0) {
                childregs->regs[28] = (unsigned long) ti;
index e000b278f0243cfdfa1986be89b728c5b371a480..9dbe58368953809f721e845a004f98cb57809dba 100644 (file)
@@ -100,7 +100,7 @@ void __init device_tree_init(void)
                return;
 
        base = virt_to_phys((void *)initial_boot_params);
-       size = initial_boot_params->totalsize;
+       size = be32_to_cpu(initial_boot_params->totalsize);
 
        /* Before we do anything, lets reserve the dt blob */
        reserve_mem_mach(base, size);
index 43e7cdc5ded23a42fa1a8f24376ddf60eb96ccac..c0e81418ba21281ea4f3b5cedff5e564f947c1a1 100644 (file)
@@ -153,7 +153,7 @@ static void __cpuinit vsmp_init_secondary(void)
 {
        extern int gic_present;
 
-       /* This is Malta specific: IPI,performance and timer inetrrupts */
+       /* This is Malta specific: IPI,performance and timer interrupts */
        if (gic_present)
                change_c0_status(ST0_IM, STATUSF_IP3 | STATUSF_IP4 |
                                         STATUSF_IP6 | STATUSF_IP7);
index 8e9fbe75894e5f5199618264fcddde6410d42dc7..e97104302541fd4111ae9ceca477e04cf2b5add7 100644 (file)
@@ -83,7 +83,8 @@ extern asmlinkage void handle_mcheck(void);
 extern asmlinkage void handle_reserved(void);
 
 extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,
-       struct mips_fpu_struct *ctx, int has_fpu);
+                                   struct mips_fpu_struct *ctx, int has_fpu,
+                                   void *__user *fault_addr);
 
 void (*board_be_init)(void);
 int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
@@ -661,12 +662,36 @@ asmlinkage void do_ov(struct pt_regs *regs)
        force_sig_info(SIGFPE, &info, current);
 }
 
+static int process_fpemu_return(int sig, void __user *fault_addr)
+{
+       if (sig == SIGSEGV || sig == SIGBUS) {
+               struct siginfo si = {0};
+               si.si_addr = fault_addr;
+               si.si_signo = sig;
+               if (sig == SIGSEGV) {
+                       if (find_vma(current->mm, (unsigned long)fault_addr))
+                               si.si_code = SEGV_ACCERR;
+                       else
+                               si.si_code = SEGV_MAPERR;
+               } else {
+                       si.si_code = BUS_ADRERR;
+               }
+               force_sig_info(sig, &si, current);
+               return 1;
+       } else if (sig) {
+               force_sig(sig, current);
+               return 1;
+       } else {
+               return 0;
+       }
+}
+
 /*
  * XXX Delayed fp exceptions when doing a lazy ctx switch XXX
  */
 asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 {
-       siginfo_t info;
+       siginfo_t info = {0};
 
        if (notify_die(DIE_FP, "FP exception", regs, 0, regs_to_trapnr(regs), SIGFPE)
            == NOTIFY_STOP)
@@ -675,6 +700,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
 
        if (fcr31 & FPU_CSR_UNI_X) {
                int sig;
+               void __user *fault_addr = NULL;
 
                /*
                 * Unimplemented operation exception.  If we've got the full
@@ -690,7 +716,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                lose_fpu(1);
 
                /* Run the emulator */
-               sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1);
+               sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
+                                              &fault_addr);
 
                /*
                 * We can't allow the emulated instruction to leave any of
@@ -702,8 +729,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
                own_fpu(1);     /* Using the FPU again.  */
 
                /* If something went wrong, signal */
-               if (sig)
-                       force_sig(sig, current);
+               process_fpemu_return(sig, fault_addr);
 
                return;
        } else if (fcr31 & FPU_CSR_INV_X)
@@ -996,11 +1022,11 @@ asmlinkage void do_cpu(struct pt_regs *regs)
 
                if (!raw_cpu_has_fpu) {
                        int sig;
+                       void __user *fault_addr = NULL;
                        sig = fpu_emulator_cop1Handler(regs,
-                                               &current->thread.fpu, 0);
-                       if (sig)
-                               force_sig(sig, current);
-                       else
+                                                      &current->thread.fpu,
+                                                      0, &fault_addr);
+                       if (!process_fpemu_return(sig, fault_addr))
                                mt_ase_fp_affinity();
                }
 
index 3eb3cde2f66160c0b4f5aeee889dc9adbfedf823..6a1fdfef8fded5763a457ec026467b356717fc78 100644 (file)
@@ -1092,6 +1092,10 @@ static int vpe_open(struct inode *inode, struct file *filp)
 
        /* this of-course trashes what was there before... */
        v->pbuffer = vmalloc(P_SIZE);
+       if (!v->pbuffer) {
+               pr_warning("VPE loader: unable to allocate memory\n");
+               return -ENOMEM;
+       }
        v->plen = P_SIZE;
        v->load_addr = NULL;
        v->len = 0;
@@ -1149,10 +1153,9 @@ static int vpe_release(struct inode *inode, struct file *filp)
        if (ret < 0)
                v->shared_ptr = NULL;
 
-       // cleanup any temp buffers
-       if (v->pbuffer)
-               vfree(v->pbuffer);
+       vfree(v->pbuffer);
        v->plen = 0;
+
        return ret;
 }
 
@@ -1169,11 +1172,6 @@ static ssize_t vpe_write(struct file *file, const char __user * buffer,
        if (v == NULL)
                return -ENODEV;
 
-       if (v->pbuffer == NULL) {
-               printk(KERN_ERR "VPE loader: no buffer for program\n");
-               return -ENOMEM;
-       }
-
        if ((count + v->len) > v->plen) {
                printk(KERN_WARNING
                       "VPE loader: elf size too big. Perhaps strip uneeded symbols\n");
index 77dc3b20110ab9d583e09a9cac94e865bc2deab1..606c8a9efe3bb146930aca3b7c438f0095cbe066 100644 (file)
@@ -161,16 +161,16 @@ FEXPORT(__bzero)
 
 .Lfwd_fixup:
        PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
        andi            a2, 0x3f
+       LONG_L          t0, THREAD_BUADDR(t0)
        LONG_ADDU       a2, t1
        jr              ra
         LONG_SUBU      a2, t0
 
 .Lpartial_fixup:
        PTR_L           t0, TI_TASK($28)
-       LONG_L          t0, THREAD_BUADDR(t0)
        andi            a2, LONGMASK
+       LONG_L          t0, THREAD_BUADDR(t0)
        LONG_ADDU       a2, t1
        jr              ra
         LONG_SUBU      a2, t0
index ae4cff97a56c5073d75925a7c89a94ee5a410513..11b193f848f88b7aa1c5ab5a842c2cf4e80ed7d7 100644 (file)
@@ -29,9 +29,9 @@ unsigned long memsize, highmemsize;
 
 #define parse_even_earlier(res, option, p)                             \
 do {                                                                   \
+       int ret;                                                        \
        if (strncmp(option, (char *)p, strlen(option)) == 0)            \
-                       strict_strtol((char *)p + strlen(option"="),    \
-                                       10, &res);                      \
+               ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \
 } while (0)
 
 void __init prom_init_env(void)
index b2ad1b0910ffb86d009dac8769310f30af3c3fcc..d32cb050311053a8e873ea470617b0ec17f13e26 100644 (file)
@@ -64,7 +64,7 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
 
 #if __mips >= 4 && __mips != 32
 static int fpux_emu(struct pt_regs *,
-       struct mips_fpu_struct *, mips_instruction);
+       struct mips_fpu_struct *, mips_instruction, void *__user *);
 #endif
 
 /* Further private data for which no space exists in mips_fpu_struct */
@@ -208,16 +208,23 @@ static inline int cop1_64bit(struct pt_regs *xcp)
  * Two instructions if the instruction is in a branch delay slot.
  */
 
-static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
+static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+                      void *__user *fault_addr)
 {
        mips_instruction ir;
        unsigned long emulpc, contpc;
        unsigned int cond;
 
-       if (get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+       if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {
                MIPS_FPU_EMU_INC_STATS(errors);
+               *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                return SIGBUS;
        }
+       if (__get_user(ir, (mips_instruction __user *) xcp->cp0_epc)) {
+               MIPS_FPU_EMU_INC_STATS(errors);
+               *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+               return SIGSEGV;
+       }
 
        /* XXX NEC Vr54xx bug workaround */
        if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
@@ -245,10 +252,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 #endif
                        return SIGILL;
                }
-               if (get_user(ir, (mips_instruction __user *) emulpc)) {
+               if (!access_ok(VERIFY_READ, emulpc, sizeof(mips_instruction))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)emulpc;
                        return SIGBUS;
                }
+               if (__get_user(ir, (mips_instruction __user *) emulpc)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)emulpc;
+                       return SIGSEGV;
+               }
                /* __compute_return_epc() will have updated cp0_epc */
                contpc = xcp->cp0_epc;
                /* In order not to confuse ptrace() et al, tweak context */
@@ -269,10 +282,17 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                u64 val;
 
                MIPS_FPU_EMU_INC_STATS(loads);
-               if (get_user(val, va)) {
+
+               if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__get_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                DITOREG(val, MIPSInst_RT(ir));
                break;
        }
@@ -284,10 +304,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                MIPS_FPU_EMU_INC_STATS(stores);
                DIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__put_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                break;
        }
 
@@ -297,10 +323,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                u32 val;
 
                MIPS_FPU_EMU_INC_STATS(loads);
-               if (get_user(val, va)) {
+               if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__get_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                SITOREG(val, MIPSInst_RT(ir));
                break;
        }
@@ -312,10 +344,16 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
                MIPS_FPU_EMU_INC_STATS(stores);
                SIFROMREG(val, MIPSInst_RT(ir));
-               if (put_user(val, va)) {
+               if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
                        return SIGBUS;
                }
+               if (__put_user(val, va)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = va;
+                       return SIGSEGV;
+               }
                break;
        }
 
@@ -440,11 +478,18 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
                                contpc = (xcp->cp0_epc +
                                        (MIPSInst_SIMM(ir) << 2));
 
-                               if (get_user(ir,
-                                   (mips_instruction __user *) xcp->cp0_epc)) {
+                               if (!access_ok(VERIFY_READ, xcp->cp0_epc,
+                                              sizeof(mips_instruction))) {
                                        MIPS_FPU_EMU_INC_STATS(errors);
+                                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                                        return SIGBUS;
                                }
+                               if (__get_user(ir,
+                                   (mips_instruction __user *) xcp->cp0_epc)) {
+                                       MIPS_FPU_EMU_INC_STATS(errors);
+                                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+                                       return SIGSEGV;
+                               }
 
                                switch (MIPSInst_OPCODE(ir)) {
                                case lwc1_op:
@@ -506,9 +551,8 @@ static int cop1Emulate(struct pt_regs *xcp, struct mips_fpu_struct *ctx)
 
 #if __mips >= 4 && __mips != 32
        case cop1x_op:{
-               int sig;
-
-               if ((sig = fpux_emu(xcp, ctx, ir)))
+               int sig = fpux_emu(xcp, ctx, ir, fault_addr);
+               if (sig)
                        return sig;
                break;
        }
@@ -604,7 +648,7 @@ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
 DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
 
 static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
-       mips_instruction ir)
+       mips_instruction ir, void *__user *fault_addr)
 {
        unsigned rcsr = 0;      /* resulting csr */
 
@@ -624,10 +668,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        MIPS_FPU_EMU_INC_STATS(loads);
-                       if (get_user(val, va)) {
+                       if (!access_ok(VERIFY_READ, va, sizeof(u32))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__get_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        SITOREG(val, MIPSInst_FD(ir));
                        break;
 
@@ -638,10 +688,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                        MIPS_FPU_EMU_INC_STATS(stores);
 
                        SIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (!access_ok(VERIFY_WRITE, va, sizeof(u32))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (put_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        break;
 
                case madd_s_op:
@@ -701,10 +757,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                                xcp->regs[MIPSInst_FT(ir)]);
 
                        MIPS_FPU_EMU_INC_STATS(loads);
-                       if (get_user(val, va)) {
+                       if (!access_ok(VERIFY_READ, va, sizeof(u64))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__get_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        DITOREG(val, MIPSInst_FD(ir));
                        break;
 
@@ -714,10 +776,16 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 
                        MIPS_FPU_EMU_INC_STATS(stores);
                        DIFROMREG(val, MIPSInst_FS(ir));
-                       if (put_user(val, va)) {
+                       if (!access_ok(VERIFY_WRITE, va, sizeof(u64))) {
                                MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
                                return SIGBUS;
                        }
+                       if (__put_user(val, va)) {
+                               MIPS_FPU_EMU_INC_STATS(errors);
+                               *fault_addr = va;
+                               return SIGSEGV;
+                       }
                        break;
 
                case madd_d_op:
@@ -1242,7 +1310,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
 }
 
 int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
-       int has_fpu)
+       int has_fpu, void *__user *fault_addr)
 {
        unsigned long oldepc, prevepc;
        mips_instruction insn;
@@ -1252,10 +1320,16 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
        do {
                prevepc = xcp->cp0_epc;
 
-               if (get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+               if (!access_ok(VERIFY_READ, xcp->cp0_epc, sizeof(mips_instruction))) {
                        MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
                        return SIGBUS;
                }
+               if (__get_user(insn, (mips_instruction __user *) xcp->cp0_epc)) {
+                       MIPS_FPU_EMU_INC_STATS(errors);
+                       *fault_addr = (mips_instruction __user *)xcp->cp0_epc;
+                       return SIGSEGV;
+               }
                if (insn == 0)
                        xcp->cp0_epc += 4;      /* skip nops */
                else {
@@ -1267,7 +1341,7 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
                         */
                        /* convert to ieee library modes */
                        ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
-                       sig = cop1Emulate(xcp, ctx);
+                       sig = cop1Emulate(xcp, ctx, fault_addr);
                        /* revert to mips rounding mode */
                        ieee754_csr.rm = mips_rm[ieee754_csr.rm];
                }
index 4fc1a0fbe0074e154c64a89f8f40d90bd6e1bd91..21ea14efb83747c5275858c6b64a18b6ea040131 100644 (file)
@@ -288,7 +288,7 @@ int mips_dma_supported(struct device *dev, u64 mask)
        return plat_dma_supported(dev, mask);
 }
 
-void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                         enum dma_data_direction direction)
 {
        BUG_ON(direction == DMA_NONE);
@@ -298,6 +298,8 @@ void mips_dma_cache_sync(struct device *dev, void *vaddr, size_t size,
                __dma_sync((unsigned long)vaddr, size, direction);
 }
 
+EXPORT_SYMBOL(dma_cache_sync);
+
 static struct dma_map_ops mips_default_dma_map_ops = {
        .alloc_coherent = mips_dma_alloc_coherent,
        .free_coherent = mips_dma_free_coherent,
index 505fecad4684f272b7a00d6dd8e3f3098875df4c..9cca8de0054507ca3869071d6bc72dab01e13170 100644 (file)
@@ -68,6 +68,9 @@ static struct bcache_ops mips_sc_ops = {
  */
 static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
 {
+       unsigned int config2 = read_c0_config2();
+       unsigned int tmp;
+
        /* Check the bypass bit (L2B) */
        switch (c->cputype) {
        case CPU_34K:
@@ -83,6 +86,7 @@ static inline int mips_sc_is_activated(struct cpuinfo_mips *c)
                c->scache.linesz = 2 << tmp;
        else
                return 0;
+       return 1;
 }
 
 static inline int __init mips_sc_probe(void)
index b7f1d9c4a8a3c7d588b270d6bd6e1bad0590f6b2..434d7b1a8c6a7abf4c492a14b975111a21b1a4ab 100644 (file)
@@ -65,11 +65,15 @@ static unsigned char readb_outer_space(unsigned long long phys)
 
        __asm__ __volatile__ (
        "       .set    mips3           \n"
+       "       .set    push            \n"
+       "       .set    noreorder       \n"
+       "       .set    nomacro         \n"
        "       ld      %0, %1          \n"
+       "       .set    pop             \n"
        "       lbu     %0, (%0)        \n"
        "       .set    mips0           \n"
        : "=r" (res)
-       : "m" (vaddr));
+       : "R" (vaddr));
 
        write_c0_status(sr);
        ssnop_4();
@@ -89,11 +93,15 @@ static void writeb_outer_space(unsigned long long phys, unsigned char c)
 
        __asm__ __volatile__ (
        "       .set    mips3           \n"
+       "       .set    push            \n"
+       "       .set    noreorder       \n"
+       "       .set    nomacro         \n"
        "       ld      %0, %1          \n"
+       "       .set    pop             \n"
        "       sb      %2, (%0)        \n"
        "       .set    mips0           \n"
        : "=&r" (tmp)
-       : "m" (vaddr), "r" (c));
+       : "R" (vaddr), "r" (c));
 
        write_c0_status(sr);
        ssnop_4();
index c308989fc464c3c76a1bc258d38713543c4004c8..41707a245dea61c1cabd467f2bc3d2ec2ca28cd8 100644 (file)
@@ -82,7 +82,7 @@ int swarm_be_handler(struct pt_regs *regs, int is_fixup)
 enum swarm_rtc_type {
        RTC_NONE,
        RTC_XICOR,
-       RTC_M4LT81
+       RTC_M41T81,
 };
 
 enum swarm_rtc_type swarm_rtc_type;
@@ -96,7 +96,7 @@ void read_persistent_clock(struct timespec *ts)
                sec = xicor_get_time();
                break;
 
-       case RTC_M4LT81:
+       case RTC_M41T81:
                sec = m41t81_get_time();
                break;
 
@@ -115,7 +115,7 @@ int rtc_mips_set_time(unsigned long sec)
        case RTC_XICOR:
                return xicor_set_time(sec);
 
-       case RTC_M4LT81:
+       case RTC_M41T81:
                return m41t81_set_time(sec);
 
        case RTC_NONE:
@@ -141,7 +141,7 @@ void __init plat_mem_setup(void)
        if (xicor_probe())
                swarm_rtc_type = RTC_XICOR;
        if (m41t81_probe())
-               swarm_rtc_type = RTC_M4LT81;
+               swarm_rtc_type = RTC_M41T81;
 
 #ifdef CONFIG_VT
        screen_info = (struct screen_info) {
index c2e44597c22b1fc5b69ebf13cca307d43c2d1a52..ac11754ecec544c965c196f9dc857b2b398b22e0 100644 (file)
@@ -459,7 +459,7 @@ void migrate_irqs(void)
                        tmp = CROSS_GxICR(irq, new);
 
                        x &= GxICR_LEVEL | GxICR_ENABLE;
-                       if (GxICR(irq) & GxICR_REQUEST) {
+                       if (GxICR(irq) & GxICR_REQUEST)
                                x |= GxICR_REQUEST | GxICR_DETECT;
                        CROSS_GxICR(irq, new) = x;
                        tmp = CROSS_GxICR(irq, new);
index f860a340acc920e0565f4d341fa263b5c8ea49a5..75da468090b90342ef5ff2566389b6efa1b28487 100644 (file)
@@ -40,21 +40,17 @@ unsigned long long sched_clock(void)
                unsigned long long ll;
                unsigned l[2];
        } tsc64, result;
-       unsigned long tsc, tmp;
+       unsigned long tmp;
        unsigned product[3]; /* 96-bit intermediate value */
 
        /* cnt32_to_63() is not safe with preemption */
        preempt_disable();
 
-       /* read the TSC value
-        */
-       tsc = get_cycles();
-
-       /* expand to 64-bits.
+       /* expand the tsc to 64-bits.
         * - sched_clock() must be called once a minute or better or the
         *   following will go horribly wrong - see cnt32_to_63()
         */
-       tsc64.ll = cnt32_to_63(tsc) & 0x7fffffffffffffffULL;
+       tsc64.ll = cnt32_to_63(get_cycles()) & 0x7fffffffffffffffULL;
 
        preempt_enable();
 
index fea833e18ad58ab92c78da66e35e2f23dcacd8ff..e0d703c7fdf7cc3e7d1491a963db90ad4735b9e4 100644 (file)
@@ -63,6 +63,7 @@
 #include <linux/of_gpio.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/fs.h>
 #include <linux/watchdog.h>
 #include <linux/miscdevice.h>
 #include <linux/uaccess.h>
index 2e9d78d21fd36f9648286b2eb46df84beb4c9816..25cf0b34dffdca99f68fd52cec55f2b0bc870fb8 100644 (file)
@@ -1,7 +1,7 @@
 config SUPERH
        def_bool y
        select EMBEDDED
-       select HAVE_CLK
+       select CLKDEV_LOOKUP
        select HAVE_IDE if HAS_IOPORT
        select HAVE_MEMBLOCK
        select HAVE_OPROFILE
index a5ecfbacaf36b37c3f812c5ca9b2189a3c077447..87618c91d1781881140d7e55fbf7e2a718d1c142 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/usb/r8a66597.h>
 #include <linux/usb/m66592.h>
+#include <linux/clkdev.h>
 #include <net/ax88796.h>
 #include <asm/machvec.h>
 #include <mach/highlander.h>
-#include <asm/clkdev.h>
 #include <asm/clock.h>
 #include <asm/heartbeat.h>
 #include <asm/io.h>
index d961949600fd462199f3d9706e86371e815e7b1b..9070d7e607047fccec2d51b865dfe89307cd5d41 100644 (file)
@@ -140,7 +140,7 @@ void __init init_se7206_IRQ(void)
        make_se7206_irq(IRQ1_IRQ); /* ATA */
        make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
 
-       __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR); /* ICR1 */
+       __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */
 
        /* FPGA System register setup*/
        __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */
index 5645f358128b62586ccfdcaf42022deb2db5c3ce..6ba91868201ce947f625a5c982c0b4ec3a290653 100644 (file)
@@ -1,9 +1,5 @@
 /*
- *  arch/sh/include/asm/clkdev.h
- *
- * Cloned from arch/arm/include/asm/clkdev.h:
- *
- *  Copyright (C) 2008 Russell King.
+ *  Copyright (C) 2010 Paul Mundt <lethal@linux-sh.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
  *
  * Helper for the clk API to assist looking up a struct clk.
  */
-#ifndef __ASM_CLKDEV_H
-#define __ASM_CLKDEV_H
 
-struct clk;
+#ifndef __CLKDEV__H_
+#define __CLKDEV__H_
 
-struct clk_lookup {
-       struct list_head        node;
-       const char              *dev_id;
-       const char              *con_id;
-       struct clk              *clk;
-};
+#include <linux/bootmem.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-       const char *dev_fmt, ...);
+#include <asm/clock.h>
 
-void clkdev_add(struct clk_lookup *cl);
-void clkdev_drop(struct clk_lookup *cl);
+static inline struct clk_lookup_alloc *__clkdev_alloc(size_t size)
+{
+       if (!slab_is_available())
+               return alloc_bootmem_low_pages(size);
+       else
+               return kzalloc(size, GFP_KERNEL);
+}
 
-void clkdev_add_table(struct clk_lookup *, size_t);
-int clk_add_alias(const char *, const char *, char *, struct device *);
+#define __clk_put(clk)
+#define __clk_get(clk) ({ 1; })
 
-#endif
+#endif /* __CLKDEV_H__ */
index 8eed6a4854463418c26dfd7410874481706e5adf..cf652217952382622273c6c0663b958cb9d42824 100644 (file)
@@ -11,7 +11,7 @@ endif
 
 CFLAGS_REMOVE_return_address.o = -pg
 
-obj-y  := clkdev.o debugtraps.o dma-nommu.o dumpstack.o                \
+obj-y  := debugtraps.o dma-nommu.o dumpstack.o                 \
           idle.o io.o irq.o irq_$(BITS).o kdebugfs.o                   \
           machvec.o nmi_debug.o process.o                              \
           process_$(BITS).o ptrace.o ptrace_$(BITS).o                  \
diff --git a/arch/sh/kernel/clkdev.c b/arch/sh/kernel/clkdev.c
deleted file mode 100644 (file)
index 1f800ef..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * arch/sh/kernel/clkdev.c
- *
- * Cloned from arch/arm/common/clkdev.c:
- *
- *  Copyright (C) 2008 Russell King.
- *
- * 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.
- *
- * Helper for the clk API to assist looking up a struct clk.
- */
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/err.h>
-#include <linux/string.h>
-#include <linux/mutex.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/bootmem.h>
-#include <linux/mm.h>
-#include <asm/clock.h>
-#include <asm/clkdev.h>
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-
-/*
- * Find the correct struct clk for the device and connection ID.
- * We do slightly fuzzy matching here:
- *  An entry with a NULL ID is assumed to be a wildcard.
- *  If an entry has a device ID, it must match
- *  If an entry has a connection ID, it must match
- * Then we take the most specific entry - with the following
- * order of precedence: dev+con > dev only > con only.
- */
-static struct clk *clk_find(const char *dev_id, const char *con_id)
-{
-       struct clk_lookup *p;
-       struct clk *clk = NULL;
-       int match, best = 0;
-
-       list_for_each_entry(p, &clocks, node) {
-               match = 0;
-               if (p->dev_id) {
-                       if (!dev_id || strcmp(p->dev_id, dev_id))
-                               continue;
-                       match += 2;
-               }
-               if (p->con_id) {
-                       if (!con_id || strcmp(p->con_id, con_id))
-                               continue;
-                       match += 1;
-               }
-               if (match == 0)
-                       continue;
-
-               if (match > best) {
-                       clk = p->clk;
-                       best = match;
-               }
-       }
-       return clk;
-}
-
-struct clk *clk_get_sys(const char *dev_id, const char *con_id)
-{
-       struct clk *clk;
-
-       mutex_lock(&clocks_mutex);
-       clk = clk_find(dev_id, con_id);
-       mutex_unlock(&clocks_mutex);
-
-       return clk ? clk : ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get_sys);
-
-void clkdev_add(struct clk_lookup *cl)
-{
-       mutex_lock(&clocks_mutex);
-       list_add_tail(&cl->node, &clocks);
-       mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clkdev_add);
-
-void __init clkdev_add_table(struct clk_lookup *cl, size_t num)
-{
-       mutex_lock(&clocks_mutex);
-       while (num--) {
-               list_add_tail(&cl->node, &clocks);
-               cl++;
-       }
-       mutex_unlock(&clocks_mutex);
-}
-
-#define MAX_DEV_ID     20
-#define MAX_CON_ID     16
-
-struct clk_lookup_alloc {
-       struct clk_lookup cl;
-       char    dev_id[MAX_DEV_ID];
-       char    con_id[MAX_CON_ID];
-};
-
-struct clk_lookup * __init_refok
-clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
-{
-       struct clk_lookup_alloc *cla;
-
-       if (!slab_is_available())
-               cla = alloc_bootmem_low_pages(sizeof(*cla));
-       else
-               cla = kzalloc(sizeof(*cla), GFP_KERNEL);
-
-       if (!cla)
-               return NULL;
-
-       cla->cl.clk = clk;
-       if (con_id) {
-               strlcpy(cla->con_id, con_id, sizeof(cla->con_id));
-               cla->cl.con_id = cla->con_id;
-       }
-
-       if (dev_fmt) {
-               va_list ap;
-
-               va_start(ap, dev_fmt);
-               vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap);
-               cla->cl.dev_id = cla->dev_id;
-               va_end(ap);
-       }
-
-       return &cla->cl;
-}
-EXPORT_SYMBOL(clkdev_alloc);
-
-int clk_add_alias(const char *alias, const char *alias_dev_name, char *id,
-       struct device *dev)
-{
-       struct clk *r = clk_get(dev, id);
-       struct clk_lookup *l;
-
-       if (IS_ERR(r))
-               return PTR_ERR(r);
-
-       l = clkdev_alloc(r, alias, alias_dev_name);
-       clk_put(r);
-       if (!l)
-               return -ENODEV;
-       clkdev_add(l);
-       return 0;
-}
-EXPORT_SYMBOL(clk_add_alias);
-
-/*
- * clkdev_drop - remove a clock dynamically allocated
- */
-void clkdev_drop(struct clk_lookup *cl)
-{
-       struct clk_lookup_alloc *cla = container_of(cl, struct clk_lookup_alloc, cl);
-
-       mutex_lock(&clocks_mutex);
-       list_del(&cl->node);
-       mutex_unlock(&clocks_mutex);
-       kfree(cla);
-}
-EXPORT_SYMBOL(clkdev_drop);
index e2f63d68da5153d2d754798719b0f3f7fde39c8d..dd0e0f2113598801270737de56eb3c8d4672a112 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/compiler.h>
 #include <linux/slab.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 static struct clk master_clk = {
index 50f887dda56550bde11bc85101000ca224a4e75a..4187cf4fe18583b74533536e9c491dee3246dcc9 100644 (file)
@@ -48,20 +48,4 @@ int __init clk_init(void)
        return ret;
 }
 
-/*
- * Returns a clock. Note that we first try to use device id on the bus
- * and clock name. If this fails, we try to use clock name only.
- */
-struct clk *clk_get(struct device *dev, const char *con_id)
-{
-       const char *dev_id = dev ? dev_name(dev) : NULL;
-
-       return clk_get_sys(dev_id, con_id);
-}
-EXPORT_SYMBOL_GPL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL_GPL(clk_put);
 
index b26264dc2aefef75e0292cb6c9a4862e8b4f9785..c509c40cba4bfefe3917f5eec9b2ddea3c63763d 100644 (file)
@@ -34,7 +34,7 @@ static const int pfc_divisors[]={1,2,3,4,6,8,12};
 
 static void master_clk_init(struct clk *clk)
 {
-       return 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
+       clk->rate = 10000000 * PLL2 * pll1rate[(__raw_readw(FREQCR) >> 8) & 0x0007];
 }
 
 static struct clk_ops sh7201_master_clk_ops = {
index b601fa3978d1995f53ea466e6aed5145e6ef1f75..3f6f8e98635ce65a4737b07a71cd600096f5b58f 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
@@ -81,8 +81,7 @@ static void shoc_clk_init(struct clk *clk)
        for (i = 0; i < ARRAY_SIZE(frqcr3_divisors); i++) {
                int divisor = frqcr3_divisors[i];
 
-               if (clk->ops->set_rate(clk, clk->parent->rate /
-                                               divisor, 0) == 0)
+               if (clk->ops->set_rate(clk, clk->parent->rate / divisor) == 0)
                        break;
        }
 
index 71291ae201b9f4ed0c5693bdbe3dfd529795ad29..93c646072c1b93005bb6b13dff60c5afeb882854 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 /* SH7343 registers */
index 7ce5bbcd4084d0fd8efc4032ace6a11241e27b13..049dc0628ccc196d48c75a0aa4f8a2469f0575f2 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 
 /* SH7366 registers */
index 2030f3d9fac7e59ddcb725295e4bf555bf272223..9d23a36f0647b97a6b5afc24ac4f7078262f57b1 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7722.h>
index d3938f0d37029775743265fe46319d0d03b9c70f..55493cd5bd8f3b5ce3860431882c6341539d2efb 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7723.h>
index 271c0b325a9a4d7f5dde40a45152546b7aa6dce0..d08fa953c88b75939893de0083681bad61d666fb 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/clk.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/hwblk.h>
 #include <cpu/sh7724.h>
index ce39a2ae8c6cd8a8140a9bd8a09a977b75a48a27..e073e3eb4c3de8e3933a919c27ec194ab4f29e25 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
index 1f1df48008cdfaf7bfe4d15e6a2ba375c3d7583f..599630fc4d3bd952ae04bd4fb11565f7a0546a30 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <asm/io.h>
index 62d706350060089add0e76aa4c1f3b5b3fd00dac..8894926479a614234302af0f7f51fbc3e9f56266 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <asm/io.h>
index c3e458aaa2b7ecc167da7bb0d31cd51911970768..2d960247f3ebff7e8e4b55865176ed3244b0aa56 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/cpufreq.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 #include <cpu/sh7785.h>
index 597c9fbe49c6d88e45a248c424400422e949188f..42e403be9076da889384ec7544627bd144e47f1a 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
index 4f70df6b6169cb5170261f60f28cdf4b66b4107a..1afdb93b8ccb28d9c3ce42517288934496a718cc 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
-#include <asm/clkdev.h>
+#include <linux/clkdev.h>
 #include <asm/clock.h>
 #include <asm/freq.h>
 
index c1ee1d61d44ca8a07c504b9af425df3a9c7185c7..81d92a45cd4b613e2c18add9afe153e43a5d703e 100644 (file)
@@ -25,7 +25,7 @@
 
 #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
 struct pt_regs;
-int restore_sigcontext(struct pt_regs *, struct sigcontext __user *, long *);
+int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
 int setup_sigcontext(struct sigcontext __user *, struct pt_regs *);
 void do_signal(struct pt_regs *regs);
 #endif
index 543d6a33aa26f6c02f7f41f59fcdceea1729bcd8..dbb0dfc7beceb10eaa25fd4b73579cdc620334c5 100644 (file)
@@ -290,12 +290,12 @@ long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
        return ret;
 }
 
+/* The assembly shim for this function arranges to ignore the return value. */
 long compat_sys_rt_sigreturn(struct pt_regs *regs)
 {
        struct compat_rt_sigframe __user *frame =
                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
        sigset_t set;
-       long r0;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -308,13 +308,13 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
                goto badframe;
 
-       return r0;
+       return 0;
 
 badframe:
        force_sig(SIGSEGV, current);
index f5821626247fee9891d47eca123b26440f6c025c..5eed4a02bf62335e17a39f663cd4485869f44ea5 100644 (file)
@@ -1342,8 +1342,8 @@ handle_syscall:
        lw      r20, r20
 
        /* Jump to syscall handler. */
-       jalr    r20; .Lhandle_syscall_link:
-       FEEDBACK_REENTER(handle_syscall)
+       jalr    r20
+.Lhandle_syscall_link: /* value of "lr" after "jalr r20" above */
 
        /*
         * Write our r0 onto the stack so it gets restored instead
@@ -1352,6 +1352,9 @@ handle_syscall:
        PTREGS_PTR(r29, PTREGS_OFFSET_REG(0))
        sw      r29, r0
 
+.Lsyscall_sigreturn_skip:
+       FEEDBACK_REENTER(handle_syscall)
+
        /* Do syscall trace again, if requested. */
        lw      r30, r31
        andi    r30, r30, _TIF_SYSCALL_TRACE
@@ -1536,9 +1539,24 @@ STD_ENTRY_LOCAL(bad_intr)
        };                                              \
        STD_ENDPROC(_##x)
 
+/*
+ * Special-case sigreturn to not write r0 to the stack on return.
+ * This is technically more efficient, but it also avoids difficulties
+ * in the 64-bit OS when handling 32-bit compat code, since we must not
+ * sign-extend r0 for the sigreturn return-value case.
+ */
+#define PTREGS_SYSCALL_SIGRETURN(x, reg)                \
+       STD_ENTRY(_##x);                                \
+       addli   lr, lr, .Lsyscall_sigreturn_skip - .Lhandle_syscall_link; \
+       {                                               \
+        PTREGS_PTR(reg, PTREGS_OFFSET_BASE);           \
+        j      x                                       \
+       };                                              \
+       STD_ENDPROC(_##x)
+
 PTREGS_SYSCALL(sys_execve, r3)
 PTREGS_SYSCALL(sys_sigaltstack, r2)
-PTREGS_SYSCALL(sys_rt_sigreturn, r0)
+PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)
 PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)
 
 /* Save additional callee-saves to pt_regs, put address in r4 and jump. */
index 8430f45daea6bce566cc0980db85f0d0b213af72..e90eb53173b0b5e1c2f7c3ba60ad4be38940a34d 100644 (file)
@@ -211,6 +211,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
        childregs->regs[0] = 0;         /* return value is zero */
        childregs->sp = sp;  /* override with new user stack pointer */
 
+       /*
+        * If CLONE_SETTLS is set, set "tp" in the new task to "r4",
+        * which is passed in as arg #5 to sys_clone().
+        */
+       if (clone_flags & CLONE_SETTLS)
+               childregs->tp = regs->regs[4];
+
        /*
         * Copy the callee-saved registers from the passed pt_regs struct
         * into the context-switch callee-saved registers area.
@@ -539,6 +546,7 @@ struct task_struct *__sched _switch_to(struct task_struct *prev,
        return __switch_to(prev, next, next_current_ksp0(next));
 }
 
+/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
 SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
                void __user *, parent_tidptr, void __user *, child_tidptr,
                struct pt_regs *, regs)
index 757407e36696688d59810453b1ffca8da8522a62..1260321155f1d591b85131f44d9c72ad31122626 100644 (file)
@@ -52,7 +52,7 @@ SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
  */
 
 int restore_sigcontext(struct pt_regs *regs,
-                      struct sigcontext __user *sc, long *pr0)
+                      struct sigcontext __user *sc)
 {
        int err = 0;
        int i;
@@ -75,17 +75,15 @@ int restore_sigcontext(struct pt_regs *regs,
 
        regs->faultnum = INT_SWINT_1_SIGRETURN;
 
-       err |= __get_user(*pr0, &sc->gregs[0]);
        return err;
 }
 
-/* sigreturn() returns long since it restores r0 in the interrupted code. */
+/* The assembly shim for this function arranges to ignore the return value. */
 SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
 {
        struct rt_sigframe __user *frame =
                (struct rt_sigframe __user *)(regs->sp);
        sigset_t set;
-       long r0;
 
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -98,13 +96,13 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
+       if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
        if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
                goto badframe;
 
-       return r0;
+       return 0;
 
 badframe:
        force_sig(SIGSEGV, current);
index 23f315c9f21560a10f4202676e75e4181a9c7f4a..325c05294fc40dfc662a52187eba92516e568e94 100644 (file)
@@ -355,7 +355,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap,
        if (heap > 0x3fffffffffffUL)
                error("Destination address too large");
 #else
-       if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff))
+       if (heap > ((-__PAGE_OFFSET-(128<<20)-1) & 0x7fffffff))
                error("Destination address too large");
 #endif
 #ifndef CONFIG_RELOCATABLE
index 5be1542fbfaf73bfccd03a101e94a1cca47d36b0..e99d55d74df5023d72b763ca244c9d17bbd1dd53 100644 (file)
@@ -72,6 +72,9 @@ struct e820map {
 #define BIOS_BEGIN             0x000a0000
 #define BIOS_END               0x00100000
 
+#define BIOS_ROM_BASE          0xffe00000
+#define BIOS_ROM_END           0xffffffff
+
 #ifdef __KERNEL__
 /* see comment in arch/x86/kernel/e820.c */
 extern struct e820map e820;
index 9e6fe391094e545eb41b9fa295df93a827c1fa30..f702f82aa1ebf5df3905ca32ac9326be76c03b91 100644 (file)
@@ -79,7 +79,7 @@
 #define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT)
 #define KVM_MIN_FREE_MMU_PAGES 5
 #define KVM_REFILL_PAGES 25
-#define KVM_MAX_CPUID_ENTRIES 40
+#define KVM_MAX_CPUID_ENTRIES 80
 #define KVM_NR_FIXED_MTRR_REGION 88
 #define KVM_NR_VAR_MTRR 8
 
index 9e13763b609242e0c5429a364be461a7e8fc2594..1e994754d323f400b85c5d1d7350c6e52a702ff9 100644 (file)
@@ -45,6 +45,7 @@ obj-y                 += pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
 obj-y                  += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y                  += tsc.o io_delay.o rtc.o
 obj-y                  += pci-iommu_table.o
+obj-y                  += resource.o
 
 obj-$(CONFIG_X86_TRAMPOLINE)   += trampoline.o
 obj-y                          += process.o
index 3f838d537392b4ddb6d061e82bbf1ce8a2a3b9d2..78218135b48e6169d155fb4a097e5b6c8e30e53a 100644 (file)
@@ -1389,6 +1389,14 @@ void __cpuinit end_local_APIC_setup(void)
 
        setup_apic_nmi_watchdog(NULL);
        apic_pm_activate();
+
+       /*
+        * Now that local APIC setup is completed for BP, configure the fault
+        * handling for interrupt remapping.
+        */
+       if (!smp_processor_id() && intr_remapping_enabled)
+               enable_drhd_fault_handling();
+
 }
 
 #ifdef CONFIG_X86_X2APIC
index 7cc0a721f628c302d0d420ba0bf3af1945d5a1c0..fadcd743a74f8bdcd5effbaf7e28b01ea3003532 100644 (file)
@@ -2430,13 +2430,12 @@ static void ack_apic_level(struct irq_data *data)
 {
        struct irq_cfg *cfg = data->chip_data;
        int i, do_unmask_irq = 0, irq = data->irq;
-       struct irq_desc *desc = irq_to_desc(irq);
        unsigned long v;
 
        irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
        /* If we are moving the irq we need to mask it */
-       if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
+       if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
                do_unmask_irq = 1;
                mask_ioapic(cfg);
        }
@@ -3413,6 +3412,7 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
        msg.data |= MSI_DATA_VECTOR(cfg->vector);
        msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
        msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+       msg.address_hi = MSI_ADDR_BASE_HI | MSI_ADDR_EXT_DEST_ID(dest);
 
        dmar_msi_write(irq, &msg);
 
index f9e4e6a54073e3d901d0475da9c5deceb21d55d8..d8c4a6feb2862f3a967f7eb4dcc4f503f2dac2f8 100644 (file)
@@ -79,13 +79,6 @@ void __init default_setup_apic_routing(void)
                /* need to update phys_pkg_id */
                apic->phys_pkg_id = apicid_phys_pkg_id;
        }
-
-       /*
-        * Now that apic routing model is selected, configure the
-        * fault handling for intr remapping.
-        */
-       if (intr_remapping_enabled)
-               enable_drhd_fault_handling();
 }
 
 /* Same for both flat and physical. */
index bcece91dd3116a14fa58af5c5216dbce20daa3e5..c0dbd9ac24f0d5cf7e87f8f0439275656b877f73 100644 (file)
 #define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
 #endif
 
+/* Number of possible pages in the lowmem region */
+LOWMEM_PAGES = (((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT)
+       
 /* Enough space to fit pagetables for the low memory linear map */
-MAPPING_BEYOND_END = \
-       PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+MAPPING_BEYOND_END = PAGE_TABLE_SIZE(LOWMEM_PAGES) << PAGE_SHIFT
 
 /*
  * Worst-case size of the kernel mapping we need to make:
- * the worst-case size of the kernel itself, plus the extra we need
- * to map for the linear map.
+ * a relocatable kernel can live anywhere in lowmem, so we need to be able
+ * to map all of lowmem.
  */
-KERNEL_PAGES = (KERNEL_IMAGE_SIZE + MAPPING_BEYOND_END)>>PAGE_SHIFT
+KERNEL_PAGES = LOWMEM_PAGES
 
 INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
 RESERVE_BRK(pagetables, INIT_MAP_SIZE)
@@ -620,13 +622,13 @@ ENTRY(initial_code)
 __PAGE_ALIGNED_BSS
        .align PAGE_SIZE_asm
 #ifdef CONFIG_X86_PAE
-initial_pg_pmd:
+ENTRY(initial_pg_pmd)
        .fill 1024*KPMDS,4,0
 #else
 ENTRY(initial_page_table)
        .fill 1024,4,0
 #endif
-initial_pg_fixmap:
+ENTRY(initial_pg_fixmap)
        .fill 1024,4,0
 ENTRY(empty_zero_page)
        .fill 4096,1,0
index ae03cab4352e8535946a835787c83e5c8563079b..4ff5968f12d295ac00a55ecbbae06dd97675a6c9 100644 (file)
@@ -27,6 +27,9 @@
 #define HPET_DEV_FSB_CAP               0x1000
 #define HPET_DEV_PERI_CAP              0x2000
 
+#define HPET_MIN_CYCLES                        128
+#define HPET_MIN_PROG_DELTA            (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
+
 #define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)
 
 /*
@@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void)
        /* Calculate the min / max delta */
        hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
                                                           &hpet_clockevent);
-       /* 5 usec minimum reprogramming delta. */
-       hpet_clockevent.min_delta_ns = 5000;
+       /* Setup minimum reprogramming delta. */
+       hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA,
+                                                          &hpet_clockevent);
 
        /*
         * Start hpet with the boot cpu mask and make it
@@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta,
         * the wraparound into account) nor a simple count down event
         * mode. Further the write to the comparator register is
         * delayed internally up to two HPET clock cycles in certain
-        * chipsets (ATI, ICH9,10). We worked around that by reading
-        * back the compare register, but that required another
-        * workaround for ICH9,10 chips where the first readout after
-        * write can return the old stale value. We already have a
-        * minimum delta of 5us enforced, but a NMI or SMI hitting
+        * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even
+        * longer delays. We worked around that by reading back the
+        * compare register, but that required another workaround for
+        * ICH9,10 chips where the first readout after write can
+        * return the old stale value. We already had a minimum
+        * programming delta of 5us enforced, but a NMI or SMI hitting
         * between the counter readout and the comparator write can
         * move us behind that point easily. Now instead of reading
         * the compare register back several times, we make the ETIME
         * decision based on the following: Return ETIME if the
-        * counter value after the write is less than 8 HPET cycles
+        * counter value after the write is less than HPET_MIN_CYCLES
         * away from the event or if the counter is already ahead of
-        * the event.
+        * the event. The minimum programming delta for the generic
+        * clockevents code is set to 1.5 * HPET_MIN_CYCLES.
         */
        res = (s32)(cnt - hpet_readl(HPET_COUNTER));
 
-       return res < 8 ? -ETIME : 0;
+       return res < HPET_MIN_CYCLES ? -ETIME : 0;
 }
 
 static void hpet_legacy_set_mode(enum clock_event_mode mode,
index dcb65cc0a05368ca096e4d907bffe63f9525fb93..1a1b606d3e92a879183cd720e3072b4b0832e579 100644 (file)
@@ -364,8 +364,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 
                /* For performance reasons, reuse mc area when possible */
                if (!mc || mc_size > curr_mc_size) {
-                       if (mc)
-                               vfree(mc);
+                       vfree(mc);
                        mc = vmalloc(mc_size);
                        if (!mc)
                                break;
@@ -374,13 +373,11 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
 
                if (get_ucode_data(mc, ucode_ptr, mc_size) ||
                    microcode_sanity_check(mc) < 0) {
-                       vfree(mc);
                        break;
                }
 
                if (get_matching_microcode(&uci->cpu_sig, mc, new_rev)) {
-                       if (new_mc)
-                               vfree(new_mc);
+                       vfree(new_mc);
                        new_rev = mc_header.rev;
                        new_mc  = mc;
                        mc = NULL;      /* trigger new vmalloc */
@@ -390,12 +387,10 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
                leftover  -= mc_size;
        }
 
-       if (mc)
-               vfree(mc);
+       vfree(mc);
 
        if (leftover) {
-               if (new_mc)
-                       vfree(new_mc);
+               vfree(new_mc);
                state = UCODE_ERROR;
                goto out;
        }
@@ -405,8 +400,7 @@ static enum ucode_state generic_load_microcode(int cpu, void *data, size_t size,
                goto out;
        }
 
-       if (uci->mc)
-               vfree(uci->mc);
+       vfree(uci->mc);
        uci->mc = (struct microcode_intel *)new_mc;
 
        pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
diff --git a/arch/x86/kernel/resource.c b/arch/x86/kernel/resource.c
new file mode 100644 (file)
index 0000000..2a26819
--- /dev/null
@@ -0,0 +1,48 @@
+#include <linux/ioport.h>
+#include <asm/e820.h>
+
+static void resource_clip(struct resource *res, resource_size_t start,
+                         resource_size_t end)
+{
+       resource_size_t low = 0, high = 0;
+
+       if (res->end < start || res->start > end)
+               return;         /* no conflict */
+
+       if (res->start < start)
+               low = start - res->start;
+
+       if (res->end > end)
+               high = res->end - end;
+
+       /* Keep the area above or below the conflict, whichever is larger */
+       if (low > high)
+               res->end = start - 1;
+       else
+               res->start = end + 1;
+}
+
+static void remove_e820_regions(struct resource *avail)
+{
+       int i;
+       struct e820entry *entry;
+
+       for (i = 0; i < e820.nr_map; i++) {
+               entry = &e820.map[i];
+
+               resource_clip(avail, entry->addr,
+                             entry->addr + entry->size - 1);
+       }
+}
+
+void arch_remove_reservations(struct resource *avail)
+{
+       /* Trim out BIOS areas (low 1MB and high 2MB) and E820 regions */
+       if (avail->flags & IORESOURCE_MEM) {
+               if (avail->start < BIOS_END)
+                       avail->start = BIOS_END;
+               resource_clip(avail, BIOS_ROM_BASE, BIOS_ROM_END);
+
+               remove_e820_regions(avail);
+       }
+}
index 21c6746338afef0949e89f8b2c0442654401546e..a0f52af256a037eaca0fce91e00caad47018d65d 100644 (file)
@@ -501,7 +501,18 @@ static inline unsigned long long get_total_mem(void)
        return total << PAGE_SHIFT;
 }
 
-#define DEFAULT_BZIMAGE_ADDR_MAX 0x37FFFFFF
+/*
+ * Keep the crash kernel below this limit.  On 32 bits earlier kernels
+ * would limit the kernel to the low 512 MiB due to mapping restrictions.
+ * On 64 bits, kexec-tools currently limits us to 896 MiB; increase this
+ * limit once kexec-tools are fixed.
+ */
+#ifdef CONFIG_X86_32
+# define CRASH_KERNEL_ADDR_MAX (512 << 20)
+#else
+# define CRASH_KERNEL_ADDR_MAX (896 << 20)
+#endif
+
 static void __init reserve_crashkernel(void)
 {
        unsigned long long total_mem;
@@ -520,10 +531,10 @@ static void __init reserve_crashkernel(void)
                const unsigned long long alignment = 16<<20;    /* 16M */
 
                /*
-                *  kexec want bzImage is below DEFAULT_BZIMAGE_ADDR_MAX
+                *  kexec want bzImage is below CRASH_KERNEL_ADDR_MAX
                 */
                crash_base = memblock_find_in_range(alignment,
-                              DEFAULT_BZIMAGE_ADDR_MAX, crash_size, alignment);
+                              CRASH_KERNEL_ADDR_MAX, crash_size, alignment);
 
                if (crash_base == MEMBLOCK_ERROR) {
                        pr_info("crashkernel reservation failed - No suitable area found.\n");
@@ -769,7 +780,6 @@ void __init setup_arch(char **cmdline_p)
 
        x86_init.oem.arch_setup();
 
-       resource_alloc_from_bottom = 0;
        iomem_resource.end = (1ULL << boot_cpu_data.x86_phys_bits) - 1;
        setup_memory_map();
        parse_setup_data();
index 9c253bd65e24ba3e803b044fca3ad57224a41c52..547128546cc3bd4644a189955c1b804f5c150770 100644 (file)
@@ -394,7 +394,8 @@ static void __init setup_xstate_init(void)
         * Setup init_xstate_buf to represent the init state of
         * all the features managed by the xsave
         */
-       init_xstate_buf = alloc_bootmem(xstate_size);
+       init_xstate_buf = alloc_bootmem_align(xstate_size,
+                                             __alignof__(struct xsave_struct));
        init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
 
        clts();
index f628234fbeca06683876543f07476f10111812b7..3cece05e4ac4622853c8eeb20e3bd04a02f851c7 100644 (file)
@@ -575,6 +575,8 @@ struct kvm_pic *kvm_create_pic(struct kvm *kvm)
        s->pics[1].elcr_mask = 0xde;
        s->pics[0].pics_state = s;
        s->pics[1].pics_state = s;
+       s->pics[0].isr_ack = 0xff;
+       s->pics[1].isr_ack = 0xff;
 
        /*
         * Initialize PIO device
index fb8b376bf28cb3e04a6bb903900f32838ab02a14..fbb04aee8301efab741f80f7c590a45d7e3b298f 100644 (file)
@@ -2394,7 +2394,8 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
                        ASSERT(!VALID_PAGE(root));
                        spin_lock(&vcpu->kvm->mmu_lock);
                        kvm_mmu_free_some_pages(vcpu);
-                       sp = kvm_mmu_get_page(vcpu, i << 30, i << 30,
+                       sp = kvm_mmu_get_page(vcpu, i << (30 - PAGE_SHIFT),
+                                             i << 30,
                                              PT32_ROOT_LEVEL, 1, ACC_ALL,
                                              NULL);
                        root = __pa(sp->spt);
index 1ca12298ffc74f2d783effb35da0953163bbb314..b81a9b7c2ca486f3faa8d8c8314ef4e1115e69e3 100644 (file)
@@ -3494,6 +3494,10 @@ static void svm_cpuid_update(struct kvm_vcpu *vcpu)
 static void svm_set_supported_cpuid(u32 func, struct kvm_cpuid_entry2 *entry)
 {
        switch (func) {
+       case 0x00000001:
+               /* Mask out xsave bit as long as it is not supported by SVM */
+               entry->ecx &= ~(bit(X86_FEATURE_XSAVE));
+               break;
        case 0x80000001:
                if (nested)
                        entry->ecx |= (1 << 2); /* Set SVM bit */
index ff21fdda0c53b6dbf2ca84b1e4e2300e2a659b90..81fcbe9515c59d7e68734d2d4c53fa23bb72624a 100644 (file)
@@ -4227,11 +4227,6 @@ static int vmx_get_lpage_level(void)
                return PT_PDPE_LEVEL;
 }
 
-static inline u32 bit(int bitno)
-{
-       return 1 << (bitno & 31);
-}
-
 static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
index cdac9e592aa53ee84b7e184900601ab4730354e5..b989e1f1e5d36b732d1d9c864f369b39a7459105 100644 (file)
@@ -155,11 +155,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 u64 __read_mostly host_xcr0;
 
-static inline u32 bit(int bitno)
-{
-       return 1 << (bitno & 31);
-}
-
 static void kvm_on_user_return(struct user_return_notifier *urn)
 {
        unsigned slot;
@@ -4569,9 +4564,11 @@ static void kvm_timer_init(void)
 #ifdef CONFIG_CPU_FREQ
                struct cpufreq_policy policy;
                memset(&policy, 0, sizeof(policy));
-               cpufreq_get_policy(&policy, get_cpu());
+               cpu = get_cpu();
+               cpufreq_get_policy(&policy, cpu);
                if (policy.cpuinfo.max_freq)
                        max_tsc_khz = policy.cpuinfo.max_freq;
+               put_cpu();
 #endif
                cpufreq_register_notifier(&kvmclock_cpufreq_notifier_block,
                                          CPUFREQ_TRANSITION_NOTIFIER);
@@ -5522,6 +5519,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
        mmu_reset_needed |= kvm_read_cr4(vcpu) != sregs->cr4;
        kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
+       if (sregs->cr4 & X86_CR4_OSXSAVE)
+               update_cpuid(vcpu);
        if (!is_long_mode(vcpu) && is_pae(vcpu)) {
                load_pdptrs(vcpu, vcpu->arch.walk_mmu, vcpu->arch.cr3);
                mmu_reset_needed = 1;
index 2cea414489f37caa75876e7a186e00ac93937ec1..c600da830ce0e412fa4b60365909792a9b916a4d 100644 (file)
@@ -70,6 +70,11 @@ static inline int is_paging(struct kvm_vcpu *vcpu)
        return kvm_read_cr0_bits(vcpu, X86_CR0_PG);
 }
 
+static inline u32 bit(int bitno)
+{
+       return 1 << (bitno & 31);
+}
+
 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 int kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq);
index 73b1e1a1f4891708a8714570e36ce62b15ba6fc7..4996cf5f73a07db446c2fe3e1c9fe7070662b741 100644 (file)
@@ -531,7 +531,10 @@ static void lguest_write_cr3(unsigned long cr3)
 {
        lguest_data.pgdir = cr3;
        lazy_hcall1(LHCALL_NEW_PGTABLE, cr3);
-       cr3_changed = true;
+
+       /* These two page tables are simple, linear, and used during boot */
+       if (cr3 != __pa(swapper_pg_dir) && cr3 != __pa(initial_page_table))
+               cr3_changed = true;
 }
 
 static unsigned long lguest_read_cr3(void)
@@ -703,9 +706,9 @@ static void lguest_set_pmd(pmd_t *pmdp, pmd_t pmdval)
  * to forget all of them.  Fortunately, this is very rare.
  *
  * ... except in early boot when the kernel sets up the initial pagetables,
- * which makes booting astonishingly slow: 1.83 seconds!  So we don't even tell
- * the Host anything changed until we've done the first page table switch,
- * which brings boot back to 0.25 seconds.
+ * which makes booting astonishingly slow: 48 seconds!  So we don't even tell
+ * the Host anything changed until we've done the first real page table switch,
+ * which brings boot back to 4.3 seconds.
  */
 static void lguest_set_pte(pte_t *ptep, pte_t pteval)
 {
@@ -1002,7 +1005,7 @@ static void lguest_time_init(void)
        clockevents_register_device(&lguest_clockevent);
 
        /* Finally, we unblock the timer interrupt. */
-       enable_lguest_irq(0);
+       clear_bit(0, lguest_data.blocked_interrupts);
 }
 
 /*
@@ -1349,9 +1352,6 @@ __init void lguest_init(void)
         */
        switch_to_new_gdt(0);
 
-       /* We actually boot with all memory mapped, but let's say 128MB. */
-       max_pfn_mapped = (128*1024*1024) >> PAGE_SHIFT;
-
        /*
         * The Host<->Guest Switcher lives at the top of our address space, and
         * the Host told us how big it is when we made LGUEST_INIT hypercall:
index 4f420c2f2d5534ea4ac5af20292e25c4346c3cda..e7d5382ef26344534b0883a11d02b19a82d4a9cd 100644 (file)
@@ -4,6 +4,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/thread_info.h>
 #include <asm/processor-flags.h>
+#include <asm/pgtable.h>
 
 /*G:020
  * Our story starts with the kernel booting into startup_32 in
@@ -37,9 +38,113 @@ ENTRY(lguest_entry)
        /* Set up the initial stack so we can run C code. */
        movl $(init_thread_union+THREAD_SIZE),%esp
 
+       call init_pagetables
+
        /* Jumps are relative: we're running __PAGE_OFFSET too low. */
        jmp lguest_init+__PAGE_OFFSET
 
+/*
+ * Initialize page tables.  This creates a PDE and a set of page
+ * tables, which are located immediately beyond __brk_base.  The variable
+ * _brk_end is set up to point to the first "safe" location.
+ * Mappings are created both at virtual address 0 (identity mapping)
+ * and PAGE_OFFSET for up to _end.
+ *
+ * FIXME: This code is taken verbatim from arch/x86/kernel/head_32.S: they
+ * don't have a stack at this point, so we can't just use call and ret.
+ */
+init_pagetables:
+#if PTRS_PER_PMD > 1
+#define PAGE_TABLE_SIZE(pages) (((pages) / PTRS_PER_PMD) + PTRS_PER_PGD)
+#else
+#define PAGE_TABLE_SIZE(pages) ((pages) / PTRS_PER_PGD)
+#endif
+#define pa(X) ((X) - __PAGE_OFFSET)
+
+/* Enough space to fit pagetables for the low memory linear map */
+MAPPING_BEYOND_END = \
+       PAGE_TABLE_SIZE(((1<<32) - __PAGE_OFFSET) >> PAGE_SHIFT) << PAGE_SHIFT
+#ifdef CONFIG_X86_PAE
+
+       /*
+        * In PAE mode initial_page_table is statically defined to contain
+        * enough entries to cover the VMSPLIT option (that is the top 1, 2 or 3
+        * entries). The identity mapping is handled by pointing two PGD entries
+        * to the first kernel PMD.
+        *
+        * Note the upper half of each PMD or PTE are always zero at this stage.
+        */
+
+#define KPMDS (((-__PAGE_OFFSET) >> 30) & 3) /* Number of kernel PMDs */
+
+       xorl %ebx,%ebx                          /* %ebx is kept at zero */
+
+       movl $pa(__brk_base), %edi
+       movl $pa(initial_pg_pmd), %edx
+       movl $PTE_IDENT_ATTR, %eax
+10:
+       leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PMD entry */
+       movl %ecx,(%edx)                        /* Store PMD entry */
+                                               /* Upper half already zero */
+       addl $8,%edx
+       movl $512,%ecx
+11:
+       stosl
+       xchgl %eax,%ebx
+       stosl
+       xchgl %eax,%ebx
+       addl $0x1000,%eax
+       loop 11b
+
+       /*
+        * End condition: we must map up to the end + MAPPING_BEYOND_END.
+        */
+       movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
+       cmpl %ebp,%eax
+       jb 10b
+1:
+       addl $__PAGE_OFFSET, %edi
+       movl %edi, pa(_brk_end)
+       shrl $12, %eax
+       movl %eax, pa(max_pfn_mapped)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_pg_pmd+0x1000*KPMDS-8)
+#else  /* Not PAE */
+
+page_pde_offset = (__PAGE_OFFSET >> 20);
+
+       movl $pa(__brk_base), %edi
+       movl $pa(initial_page_table), %edx
+       movl $PTE_IDENT_ATTR, %eax
+10:
+       leal PDE_IDENT_ATTR(%edi),%ecx          /* Create PDE entry */
+       movl %ecx,(%edx)                        /* Store identity PDE entry */
+       movl %ecx,page_pde_offset(%edx)         /* Store kernel PDE entry */
+       addl $4,%edx
+       movl $1024, %ecx
+11:
+       stosl
+       addl $0x1000,%eax
+       loop 11b
+       /*
+        * End condition: we must map up to the end + MAPPING_BEYOND_END.
+        */
+       movl $pa(_end) + MAPPING_BEYOND_END + PTE_IDENT_ATTR, %ebp
+       cmpl %ebp,%eax
+       jb 10b
+       addl $__PAGE_OFFSET, %edi
+       movl %edi, pa(_brk_end)
+       shrl $12, %eax
+       movl %eax, pa(max_pfn_mapped)
+
+       /* Do early initialization of the fixmap area */
+       movl $pa(initial_pg_fixmap)+PDE_IDENT_ATTR,%eax
+       movl %eax,pa(initial_page_table+0xffc)
+#endif
+       ret
+
 /*G:055
  * We create a macro which puts the assembler code between lgstart_ and lgend_
  * markers.  These templates are put in the .text section: they can't be
index a011bcc0f94331d82c8abfa7d4afdbbd0c59eff5..7d90d47655ba3310d8fb26c8ecb4a460825c662f 100644 (file)
@@ -630,21 +630,29 @@ static int __init_ibs_nmi(void)
        return 0;
 }
 
-/* initialize the APIC for the IBS interrupts if available */
+/*
+ * check and reserve APIC extended interrupt LVT offset for IBS if
+ * available
+ *
+ * init_ibs() preforms implicitly cpu-local operations, so pin this
+ * thread to its current CPU
+ */
+
 static void init_ibs(void)
 {
-       ibs_caps = get_ibs_caps();
+       preempt_disable();
 
+       ibs_caps = get_ibs_caps();
        if (!ibs_caps)
-               return;
+               goto out;
 
-       if (__init_ibs_nmi()) {
+       if (__init_ibs_nmi() < 0)
                ibs_caps = 0;
-               return;
-       }
+       else
+               printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
 
-       printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n",
-              (unsigned)ibs_caps);
+out:
+       preempt_enable();
 }
 
 static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
index c4bb261c106e16eaeab09092a9942418dba61133..b1805b78842fec1efd9da3a1cebfca74c4b25371 100644 (file)
@@ -65,21 +65,13 @@ pcibios_align_resource(void *data, const struct resource *res,
                        resource_size_t size, resource_size_t align)
 {
        struct pci_dev *dev = data;
-       resource_size_t start = round_down(res->end - size + 1, align);
+       resource_size_t start = res->start;
 
        if (res->flags & IORESOURCE_IO) {
-
-               /*
-                * If we're avoiding ISA aliases, the largest contiguous I/O
-                * port space is 256 bytes.  Clearing bits 9 and 10 preserves
-                * all 256-byte and smaller alignments, so the result will
-                * still be correctly aligned.
-                */
-               if (!skip_isa_ioresource_align(dev))
-                       start &= ~0x300;
-       } else if (res->flags & IORESOURCE_MEM) {
-               if (start < BIOS_END)
-                       start = res->end;       /* fail; no space */
+               if (skip_isa_ioresource_align(dev))
+                       return start;
+               if (start & 0x300)
+                       start = (start + 0x3ff) & ~0x3ff;
        }
        return start;
 }
index 4a2afa1bac51f58d35e27ff6ffd18c4efc064f4b..b6552b189bcdbb43b1f3627616f1f69d488f9efa 100644 (file)
@@ -25,7 +25,7 @@ targets += vdso.so vdso.so.dbg vdso.lds $(vobjs-y)
 
 export CPPFLAGS_vdso.lds += -P -C
 
-VDSO_LDFLAGS_vdso.lds = -m elf_x86_64 -Wl,-soname=linux-vdso.so.1 \
+VDSO_LDFLAGS_vdso.lds = -m64 -Wl,-soname=linux-vdso.so.1 \
                        -Wl,-z,max-page-size=4096 -Wl,-z,common-page-size=4096
 
 $(obj)/vdso.o: $(src)/vdso.S $(obj)/vdso.so
@@ -69,7 +69,7 @@ vdso32.so-$(VDSO32-y)         += sysenter
 vdso32-images                  = $(vdso32.so-y:%=vdso32-%.so)
 
 CPPFLAGS_vdso32.lds = $(CPPFLAGS_vdso.lds)
-VDSO_LDFLAGS_vdso32.lds = -m elf_i386 -Wl,-soname=linux-gate.so.1
+VDSO_LDFLAGS_vdso32.lds = -m32 -Wl,-soname=linux-gate.so.1
 
 # This makes sure the $(obj) subdirectory exists even though vdso32/
 # is not a kbuild sub-make subdirectory.
index 5d5dbe47c2285ee7ccb5f3ca784f9cdb8cb6df3e..e663ac2d8e68f70ff17ce274f3cebec16c1dd18c 100644 (file)
@@ -201,12 +201,13 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
        for (i = 0; i < iov_count; i++) {
                unsigned long uaddr = (unsigned long)iov[i].iov_base;
 
+               if (!iov[i].iov_len)
+                       return -EINVAL;
+
                if (uaddr & queue_dma_alignment(q)) {
                        unaligned = 1;
                        break;
                }
-               if (!iov[i].iov_len)
-                       return -EINVAL;
        }
 
        if (unaligned || (q->dma_pad_mask & len) || map_data)
index 77b7c26df6b50fea7a38ba0825d91583f1c4031c..74bc4a768f32e0f01e5c43f100f8663eea34c3a4 100644 (file)
@@ -21,7 +21,7 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q,
                return 0;
 
        fbio = bio;
-       cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+       cluster = blk_queue_cluster(q);
        seg_size = 0;
        nr_phys_segs = 0;
        for_each_bio(bio) {
@@ -87,7 +87,7 @@ EXPORT_SYMBOL(blk_recount_segments);
 static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
                                   struct bio *nxt)
 {
-       if (!test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+       if (!blk_queue_cluster(q))
                return 0;
 
        if (bio->bi_seg_back_size + nxt->bi_seg_front_size >
@@ -123,7 +123,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
        int nsegs, cluster;
 
        nsegs = 0;
-       cluster = test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
+       cluster = blk_queue_cluster(q);
 
        /*
         * for each bio in rq
index 701859fb9647c31a505f0218800744e3e6d0a775..36c8c1f2af18088fb5fa34f4889d2fead2556600 100644 (file)
@@ -126,7 +126,7 @@ void blk_set_default_limits(struct queue_limits *lim)
        lim->alignment_offset = 0;
        lim->io_opt = 0;
        lim->misaligned = 0;
-       lim->no_cluster = 0;
+       lim->cluster = 1;
 }
 EXPORT_SYMBOL(blk_set_default_limits);
 
@@ -229,8 +229,8 @@ void blk_queue_bounce_limit(struct request_queue *q, u64 dma_mask)
 EXPORT_SYMBOL(blk_queue_bounce_limit);
 
 /**
- * blk_queue_max_hw_sectors - set max sectors for a request for this queue
- * @q:  the request queue for the device
+ * blk_limits_max_hw_sectors - set hard and soft limit of max sectors for request
+ * @limits: the queue limits
  * @max_hw_sectors:  max hardware sectors in the usual 512b unit
  *
  * Description:
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(blk_queue_bounce_limit);
  *    per-device basis in /sys/block/<device>/queue/max_sectors_kb.
  *    The soft limit can not exceed max_hw_sectors.
  **/
-void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
+void blk_limits_max_hw_sectors(struct queue_limits *limits, unsigned int max_hw_sectors)
 {
        if ((max_hw_sectors << 9) < PAGE_CACHE_SIZE) {
                max_hw_sectors = 1 << (PAGE_CACHE_SHIFT - 9);
@@ -252,9 +252,23 @@ void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_secto
                       __func__, max_hw_sectors);
        }
 
-       q->limits.max_hw_sectors = max_hw_sectors;
-       q->limits.max_sectors = min_t(unsigned int, max_hw_sectors,
-                                     BLK_DEF_MAX_SECTORS);
+       limits->max_hw_sectors = max_hw_sectors;
+       limits->max_sectors = min_t(unsigned int, max_hw_sectors,
+                                   BLK_DEF_MAX_SECTORS);
+}
+EXPORT_SYMBOL(blk_limits_max_hw_sectors);
+
+/**
+ * blk_queue_max_hw_sectors - set max sectors for a request for this queue
+ * @q:  the request queue for the device
+ * @max_hw_sectors:  max hardware sectors in the usual 512b unit
+ *
+ * Description:
+ *    See description for blk_limits_max_hw_sectors().
+ **/
+void blk_queue_max_hw_sectors(struct request_queue *q, unsigned int max_hw_sectors)
+{
+       blk_limits_max_hw_sectors(&q->limits, max_hw_sectors);
 }
 EXPORT_SYMBOL(blk_queue_max_hw_sectors);
 
@@ -464,15 +478,6 @@ EXPORT_SYMBOL(blk_queue_io_opt);
 void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b)
 {
        blk_stack_limits(&t->limits, &b->limits, 0);
-
-       if (!t->queue_lock)
-               WARN_ON_ONCE(1);
-       else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-               unsigned long flags;
-               spin_lock_irqsave(t->queue_lock, flags);
-               queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-               spin_unlock_irqrestore(t->queue_lock, flags);
-       }
 }
 EXPORT_SYMBOL(blk_queue_stack_limits);
 
@@ -545,7 +550,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
        t->io_min = max(t->io_min, b->io_min);
        t->io_opt = lcm(t->io_opt, b->io_opt);
 
-       t->no_cluster |= b->no_cluster;
+       t->cluster &= b->cluster;
        t->discard_zeroes_data &= b->discard_zeroes_data;
 
        /* Physical block size a multiple of the logical block size? */
@@ -641,7 +646,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
                       sector_t offset)
 {
        struct request_queue *t = disk->queue;
-       struct request_queue *b = bdev_get_queue(bdev);
 
        if (bdev_stack_limits(&t->limits, bdev, offset >> 9) < 0) {
                char top[BDEVNAME_SIZE], bottom[BDEVNAME_SIZE];
@@ -652,17 +656,6 @@ void disk_stack_limits(struct gendisk *disk, struct block_device *bdev,
                printk(KERN_NOTICE "%s: Warning: Device %s is misaligned\n",
                       top, bottom);
        }
-
-       if (!t->queue_lock)
-               WARN_ON_ONCE(1);
-       else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) {
-               unsigned long flags;
-
-               spin_lock_irqsave(t->queue_lock, flags);
-               if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags))
-                       queue_flag_clear(QUEUE_FLAG_CLUSTER, t);
-               spin_unlock_irqrestore(t->queue_lock, flags);
-       }
 }
 EXPORT_SYMBOL(disk_stack_limits);
 
index 013457f47fdc8b12eded858c852f588884b962c5..41fb69150b4d3c6758b0f5da6ff2005d4d7a0a3f 100644 (file)
@@ -119,7 +119,7 @@ static ssize_t queue_max_integrity_segments_show(struct request_queue *q, char *
 
 static ssize_t queue_max_segment_size_show(struct request_queue *q, char *page)
 {
-       if (test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags))
+       if (blk_queue_cluster(q))
                return queue_var_show(queue_max_segment_size(q), (page));
 
        return queue_var_show(PAGE_CACHE_SIZE, (page));
index 004be80fd89402efbdc3f4a89a894570b7f27e59..381b09bb562b277620479fa92313cc6631995630 100644 (file)
@@ -355,6 +355,12 @@ throtl_start_new_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
                        tg->slice_end[rw], jiffies);
 }
 
+static inline void throtl_set_slice_end(struct throtl_data *td,
+               struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
+{
+       tg->slice_end[rw] = roundup(jiffy_end, throtl_slice);
+}
+
 static inline void throtl_extend_slice(struct throtl_data *td,
                struct throtl_grp *tg, bool rw, unsigned long jiffy_end)
 {
@@ -391,6 +397,16 @@ throtl_trim_slice(struct throtl_data *td, struct throtl_grp *tg, bool rw)
        if (throtl_slice_used(td, tg, rw))
                return;
 
+       /*
+        * A bio has been dispatched. Also adjust slice_end. It might happen
+        * that initially cgroup limit was very low resulting in high
+        * slice_end, but later limit was bumped up and bio was dispached
+        * sooner, then we need to reduce slice_end. A high bogus slice_end
+        * is bad because it does not allow new slice to start.
+        */
+
+       throtl_set_slice_end(td, tg, rw, jiffies + throtl_slice);
+
        time_elapsed = jiffies - tg->slice_start[rw];
 
        nr_slices = time_elapsed / throtl_slice;
@@ -709,26 +725,21 @@ static void throtl_process_limit_change(struct throtl_data *td)
        struct throtl_grp *tg;
        struct hlist_node *pos, *n;
 
-       /*
-        * Make sure atomic_inc() effects from
-        * throtl_update_blkio_group_read_bps(), group of functions are
-        * visible.
-        * Is this required or smp_mb__after_atomic_inc() was suffcient
-        * after the atomic_inc().
-        */
-       smp_rmb();
        if (!atomic_read(&td->limits_changed))
                return;
 
        throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
 
-       hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
-               /*
-                * Do I need an smp_rmb() here to make sure tg->limits_changed
-                * update is visible. I am relying on smp_rmb() at the
-                * beginning of function and not putting a new one here.
-                */
+       /*
+        * Make sure updates from throtl_update_blkio_group_read_bps() group
+        * of functions to tg->limits_changed are visible. We do not
+        * want update td->limits_changed to be visible but update to
+        * tg->limits_changed not being visible yet on this cpu. Hence
+        * the read barrier.
+        */
+       smp_rmb();
 
+       hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
                if (throtl_tg_on_rr(tg) && tg->limits_changed) {
                        throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
                                " riops=%u wiops=%u", tg->bps[READ],
index a2b902f4d43706334e87b30656b1addc399b1c77..3d93b3a3d630ca9e71f7775691a5071546f45746 100644 (file)
@@ -111,4 +111,6 @@ source "drivers/xen/Kconfig"
 source "drivers/staging/Kconfig"
 
 source "drivers/platform/Kconfig"
+
+source "drivers/clk/Kconfig"
 endmenu
index f3ebb30f1b7fd9c7ed93d6328dbe4d8c54b1fd87..bf15ce7493d274eee5b135ea194106da84db2864 100644 (file)
@@ -115,3 +115,5 @@ obj-$(CONFIG_VLYNQ)         += vlynq/
 obj-$(CONFIG_STAGING)          += staging/
 obj-y                          += platform/
 obj-y                          += ieee802154/
+#common clk code
+obj-y                          += clk/
index 2c7def95f721c6d08596c9ce852a3ac4a1c54e38..4c8dea513b66adeea7881d7f541237c812e5bf14 100644 (file)
@@ -408,6 +408,9 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
                return_ACPI_STATUS(AE_OK);
        }
 
+       /* Disable the GPE in case it's been enabled already. */
+       (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
+
        /*
         * Add the GPE information from above to the gpe_event_info block for
         * use during dispatch of this GPE.
index 9fb9d5ac939db1c071c4cdcaa7fba49364236e25..95649d373071ac93d14bbbb478db1ab4a8cdb801 100644 (file)
@@ -130,8 +130,6 @@ struct acpi_battery {
        unsigned long flags;
 };
 
-static int acpi_battery_update(struct acpi_battery *battery);
-
 #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat);
 
 inline int acpi_battery_present(struct acpi_battery *battery)
@@ -186,9 +184,6 @@ static int acpi_battery_get_property(struct power_supply *psy,
        int ret = 0;
        struct acpi_battery *battery = to_acpi_battery(psy);
 
-       if (acpi_battery_update(battery))
-               return -ENODEV;
-
        if (acpi_battery_present(battery)) {
                /* run battery update only if it is present */
                acpi_battery_get_state(battery);
index 2b6c21d86b9885571b41679586636fff3b6c53bb..29ef505c487b92efe1b12e79c2231aa85c0298ce 100644 (file)
@@ -705,54 +705,85 @@ static int acpi_bus_get_perf_flags(struct acpi_device *device)
 }
 
 static acpi_status
-acpi_bus_extract_wakeup_device_power_package(struct acpi_device *device,
-                                            union acpi_object *package)
+acpi_bus_extract_wakeup_device_power_package(acpi_handle handle,
+                                            struct acpi_device_wakeup *wakeup)
 {
-       int i = 0;
+       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+       union acpi_object *package = NULL;
        union acpi_object *element = NULL;
+       acpi_status status;
+       int i = 0;
 
-       if (!device || !package || (package->package.count < 2))
+       if (!wakeup)
                return AE_BAD_PARAMETER;
 
+       /* _PRW */
+       status = acpi_evaluate_object(handle, "_PRW", NULL, &buffer);
+       if (ACPI_FAILURE(status)) {
+               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
+               return status;
+       }
+
+       package = (union acpi_object *)buffer.pointer;
+
+       if (!package || (package->package.count < 2)) {
+               status = AE_BAD_DATA;
+               goto out;
+       }
+
        element = &(package->package.elements[0]);
-       if (!element)
-               return AE_BAD_PARAMETER;
+       if (!element) {
+               status = AE_BAD_DATA;
+               goto out;
+       }
        if (element->type == ACPI_TYPE_PACKAGE) {
                if ((element->package.count < 2) ||
                    (element->package.elements[0].type !=
                     ACPI_TYPE_LOCAL_REFERENCE)
-                   || (element->package.elements[1].type != ACPI_TYPE_INTEGER))
-                       return AE_BAD_DATA;
-               device->wakeup.gpe_device =
+                   || (element->package.elements[1].type != ACPI_TYPE_INTEGER)) {
+                       status = AE_BAD_DATA;
+                       goto out;
+               }
+               wakeup->gpe_device =
                    element->package.elements[0].reference.handle;
-               device->wakeup.gpe_number =
+               wakeup->gpe_number =
                    (u32) element->package.elements[1].integer.value;
        } else if (element->type == ACPI_TYPE_INTEGER) {
-               device->wakeup.gpe_number = element->integer.value;
-       } else
-               return AE_BAD_DATA;
+               wakeup->gpe_device = NULL;
+               wakeup->gpe_number = element->integer.value;
+       } else {
+               status = AE_BAD_DATA;
+               goto out;
+       }
 
        element = &(package->package.elements[1]);
        if (element->type != ACPI_TYPE_INTEGER) {
-               return AE_BAD_DATA;
+               status = AE_BAD_DATA;
+               goto out;
        }
-       device->wakeup.sleep_state = element->integer.value;
+       wakeup->sleep_state = element->integer.value;
 
        if ((package->package.count - 2) > ACPI_MAX_HANDLES) {
-               return AE_NO_MEMORY;
+               status = AE_NO_MEMORY;
+               goto out;
        }
-       device->wakeup.resources.count = package->package.count - 2;
-       for (i = 0; i < device->wakeup.resources.count; i++) {
+       wakeup->resources.count = package->package.count - 2;
+       for (i = 0; i < wakeup->resources.count; i++) {
                element = &(package->package.elements[i + 2]);
-               if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
-                       return AE_BAD_DATA;
+               if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
+                       status = AE_BAD_DATA;
+                       goto out;
+               }
 
-               device->wakeup.resources.handles[i] = element->reference.handle;
+               wakeup->resources.handles[i] = element->reference.handle;
        }
 
-       acpi_gpe_can_wake(device->wakeup.gpe_device, device->wakeup.gpe_number);
+       acpi_gpe_can_wake(wakeup->gpe_device, wakeup->gpe_number);
 
-       return AE_OK;
+ out:
+       kfree(buffer.pointer);
+
+       return status;
 }
 
 static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
@@ -787,26 +818,15 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device)
 static int acpi_bus_get_wakeup_device_flags(struct acpi_device *device)
 {
        acpi_status status = 0;
-       struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
-       union acpi_object *package = NULL;
        int psw_error;
 
-       /* _PRW */
-       status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
-       if (ACPI_FAILURE(status)) {
-               ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PRW"));
-               goto end;
-       }
-
-       package = (union acpi_object *)buffer.pointer;
-       status = acpi_bus_extract_wakeup_device_power_package(device, package);
+       status = acpi_bus_extract_wakeup_device_power_package(device->handle,
+                                                             &device->wakeup);
        if (ACPI_FAILURE(status)) {
                ACPI_EXCEPTION((AE_INFO, status, "Extracting _PRW package"));
                goto end;
        }
 
-       kfree(buffer.pointer);
-
        device->wakeup.flags.valid = 1;
        device->wakeup.prepare_count = 0;
        acpi_bus_set_run_wake_flags(device);
@@ -1351,6 +1371,7 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
        struct acpi_bus_ops *ops = context;
        int type;
        unsigned long long sta;
+       struct acpi_device_wakeup wakeup;
        struct acpi_device *device;
        acpi_status status;
        int result;
@@ -1360,8 +1381,10 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, u32 lvl,
                return AE_OK;
 
        if (!(sta & ACPI_STA_DEVICE_PRESENT) &&
-           !(sta & ACPI_STA_DEVICE_FUNCTIONING))
+           !(sta & ACPI_STA_DEVICE_FUNCTIONING)) {
+               acpi_bus_extract_wakeup_device_power_package(handle, &wakeup);
                return AE_CTRL_DEPTH;
+       }
 
        /*
         * We may already have an acpi_device from a previous enumeration.  If
index 2737b97522052e7a653eb9c7622132a07a6bcded..e7df019d29d44731b7eacf035b5edd5de78a3780 100644 (file)
@@ -147,6 +147,39 @@ static void amba_put_disable_pclk(struct amba_device *pcdev)
        clk_put(pclk);
 }
 
+static int amba_get_enable_vcore(struct amba_device *pcdev)
+{
+       struct regulator *vcore = regulator_get(&pcdev->dev, "vcore");
+       int ret;
+
+       pcdev->vcore = vcore;
+
+       if (IS_ERR(vcore)) {
+               /* It is OK not to supply a vcore regulator */
+               if (PTR_ERR(vcore) == -ENODEV)
+                       return 0;
+               return PTR_ERR(vcore);
+       }
+
+       ret = regulator_enable(vcore);
+       if (ret) {
+               regulator_put(vcore);
+               pcdev->vcore = ERR_PTR(-ENODEV);
+       }
+
+       return ret;
+}
+
+static void amba_put_disable_vcore(struct amba_device *pcdev)
+{
+       struct regulator *vcore = pcdev->vcore;
+
+       if (!IS_ERR(vcore)) {
+               regulator_disable(vcore);
+               regulator_put(vcore);
+       }
+}
+
 /*
  * These are the device model conversion veneers; they convert the
  * device model structures to our more specific structures.
@@ -159,6 +192,10 @@ static int amba_probe(struct device *dev)
        int ret;
 
        do {
+               ret = amba_get_enable_vcore(pcdev);
+               if (ret)
+                       break;
+
                ret = amba_get_enable_pclk(pcdev);
                if (ret)
                        break;
@@ -168,6 +205,7 @@ static int amba_probe(struct device *dev)
                        break;
 
                amba_put_disable_pclk(pcdev);
+               amba_put_disable_vcore(pcdev);
        } while (0);
 
        return ret;
@@ -180,6 +218,7 @@ static int amba_remove(struct device *dev)
        int ret = drv->remove(pcdev);
 
        amba_put_disable_pclk(pcdev);
+       amba_put_disable_vcore(pcdev);
 
        return ret;
 }
index 11ec911016c6ab3e81cefe7e202c4cc4c95762f0..36e2319264bd33d7918979105a4f641da36d3dcd 100644 (file)
@@ -128,16 +128,6 @@ config PDC_ADMA
 
          If unsure, say N.
 
-config PATA_MPC52xx
-       tristate "Freescale MPC52xx SoC internal IDE"
-       depends on PPC_MPC52xx && PPC_BESTCOMM
-       select PPC_BESTCOMM_ATA
-       help
-         This option enables support for integrated IDE controller
-         of the Freescale MPC52xx SoC.
-
-         If unsure, say N.
-
 config PATA_OCTEON_CF
        tristate "OCTEON Boot Bus Compact Flash support"
        depends on CPU_CAVIUM_OCTEON
@@ -366,7 +356,7 @@ config PATA_CS5535
 
 config PATA_CS5536
        tristate "CS5536 PATA support"
-       depends on PCI && X86 && !X86_64
+       depends on PCI
        help
          This option enables support for the AMD CS5536
          companion chip used with the Geode LX processor family.
@@ -491,6 +481,16 @@ config PATA_MARVELL
 
          If unsure, say N.
 
+config PATA_MPC52xx
+       tristate "Freescale MPC52xx SoC internal IDE"
+       depends on PPC_MPC52xx && PPC_BESTCOMM
+       select PPC_BESTCOMM_ATA
+       help
+         This option enables support for integrated IDE controller
+         of the Freescale MPC52xx SoC.
+
+         If unsure, say N.
+
 config PATA_NETCELL
        tristate "NETCELL Revolution RAID support"
        depends on PCI
index c501af5b12b959209bde413d9b8bbe35f7be5068..2b67c900a459865c694e0cf012ebcacbfd8f76bd 100644 (file)
@@ -11,7 +11,6 @@ obj-$(CONFIG_SATA_DWC)                += sata_dwc_460ex.o
 
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)         += pdc_adma.o
-obj-$(CONFIG_PATA_MPC52xx)     += pata_mpc52xx.o
 obj-$(CONFIG_PATA_OCTEON_CF)   += pata_octeon_cf.o
 obj-$(CONFIG_SATA_QSTOR)       += sata_qstor.o
 obj-$(CONFIG_SATA_SX4)         += sata_sx4.o
@@ -52,6 +51,7 @@ obj-$(CONFIG_PATA_IT821X)     += pata_it821x.o
 obj-$(CONFIG_PATA_JMICRON)     += pata_jmicron.o
 obj-$(CONFIG_PATA_MACIO)       += pata_macio.o
 obj-$(CONFIG_PATA_MARVELL)     += pata_marvell.o
+obj-$(CONFIG_PATA_MPC52xx)     += pata_mpc52xx.o
 obj-$(CONFIG_PATA_NETCELL)     += pata_netcell.o
 obj-$(CONFIG_PATA_NINJA32)     += pata_ninja32.o
 obj-$(CONFIG_PATA_NS87415)     += pata_ns87415.o
index 7f77c67d267ca454f63b5501ab1bb82d5fe9f16d..f23d6d46b95b1bf7f4f19fb657f86cadc0ccd6b7 100644 (file)
@@ -4807,9 +4807,6 @@ static void ata_verify_xfer(struct ata_queued_cmd *qc)
 {
        struct ata_device *dev = qc->dev;
 
-       if (ata_tag_internal(qc->tag))
-               return;
-
        if (ata_is_nodata(qc->tf.protocol))
                return;
 
@@ -4858,14 +4855,23 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
                if (unlikely(qc->err_mask))
                        qc->flags |= ATA_QCFLAG_FAILED;
 
-               if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
-                       /* always fill result TF for failed qc */
+               /*
+                * Finish internal commands without any further processing
+                * and always with the result TF filled.
+                */
+               if (unlikely(ata_tag_internal(qc->tag))) {
                        fill_result_tf(qc);
+                       __ata_qc_complete(qc);
+                       return;
+               }
 
-                       if (!ata_tag_internal(qc->tag))
-                               ata_qc_schedule_eh(qc);
-                       else
-                               __ata_qc_complete(qc);
+               /*
+                * Non-internal qc has failed.  Fill the result TF and
+                * summon EH.
+                */
+               if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
+                       fill_result_tf(qc);
+                       ata_qc_schedule_eh(qc);
                        return;
                }
 
index 5e590504f3aa15c6c3c73450327a0494c264d20f..17a637877d0311abb7c95c7cd6e2359be4a2c70b 100644 (file)
@@ -3275,6 +3275,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
        struct ata_port *ap = ata_is_host_link(link) ? link->ap : NULL;
        struct ata_eh_context *ehc = &link->eh_context;
        struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
+       enum ata_lpm_policy old_policy = link->lpm_policy;
        unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
        unsigned int err_mask;
        int rc;
@@ -3338,6 +3339,14 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
                goto fail;
        }
 
+       /*
+        * Low level driver acked the transition.  Issue DIPM command
+        * with the new policy set.
+        */
+       link->lpm_policy = policy;
+       if (ap && ap->slave_link)
+               ap->slave_link->lpm_policy = policy;
+
        /* host config updated, enable DIPM if transitioning to MIN_POWER */
        ata_for_each_dev(dev, link, ENABLED) {
                if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
@@ -3353,12 +3362,14 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
                }
        }
 
-       link->lpm_policy = policy;
-       if (ap && ap->slave_link)
-               ap->slave_link->lpm_policy = policy;
        return 0;
 
 fail:
+       /* restore the old policy */
+       link->lpm_policy = old_policy;
+       if (ap && ap->slave_link)
+               ap->slave_link->lpm_policy = old_policy;
+
        /* if no device or only one more chance is left, disable LPM */
        if (!dev || ehc->tries[dev->devno] <= 2) {
                ata_link_printk(link, KERN_WARNING,
index d05387d1e14be5aedf2f23dae45e86b7ed989276..484697fef3867dce2c1926f0ad50bb53de3b40e7 100644 (file)
@@ -1532,11 +1532,10 @@ static unsigned int __ata_sff_port_intr(struct ata_port *ap,
                if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR))
                        return ata_sff_idle_irq(ap);
                break;
-       case HSM_ST:
-       case HSM_ST_LAST:
-               break;
-       default:
+       case HSM_ST_IDLE:
                return ata_sff_idle_irq(ap);
+       default:
+               break;
        }
 
        /* check main status, clearing INTRQ if needed */
index 21ee23f89e88b153ee8e35af5d75c61f83f92496..628c8fae5937183f24b9a607c17f0765609a3a5e 100644 (file)
 #include <linux/delay.h>
 #include <linux/libata.h>
 #include <scsi/scsi_host.h>
+
+#ifdef CONFIG_X86_32
 #include <asm/msr.h>
+static int use_msr;
+module_param_named(msr, use_msr, int, 0644);
+MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
+#else
+#undef rdmsr   /* avoid accidental MSR usage on, e.g. x86-64 */
+#undef wrmsr
+#define rdmsr(x, y, z) do { } while (0)
+#define wrmsr(x, y, z) do { } while (0)
+#define use_msr 0
+#endif
 
 #define DRV_NAME       "pata_cs5536"
-#define DRV_VERSION    "0.0.7"
+#define DRV_VERSION    "0.0.8"
 
 enum {
        CFG                     = 0,
@@ -75,8 +87,6 @@ enum {
        IDE_ETC_NODMA           = 0x03,
 };
 
-static int use_msr;
-
 static const u32 msr_reg[4] = {
        MSR_IDE_CFG, MSR_IDE_DTC, MSR_IDE_CAST, MSR_IDE_ETC,
 };
@@ -88,7 +98,7 @@ static const u8 pci_reg[4] = {
 static inline int cs5536_read(struct pci_dev *pdev, int reg, u32 *val)
 {
        if (unlikely(use_msr)) {
-               u32 dummy;
+               u32 dummy __maybe_unused;
 
                rdmsr(msr_reg[reg], *val, dummy);
                return 0;
@@ -294,8 +304,6 @@ MODULE_DESCRIPTION("low-level driver for the CS5536 IDE controller");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, cs5536);
 MODULE_VERSION(DRV_VERSION);
-module_param_named(msr, use_msr, int, 0644);
-MODULE_PARM_DESC(msr, "Force using MSR to configure IDE function (Default: 0)");
 
 module_init(cs5536_init);
 module_exit(cs5536_exit);
index 2b464b631f22697ac5f177d371b94d5646683d8f..0b0625054a87a5697c8e4745bfd49eb2d1bf45c0 100644 (file)
@@ -392,7 +392,10 @@ static int atmtcp_attach(struct atm_vcc *vcc,int itf)
                        atm_dev_put(dev);
                        return -EMEDIUMTYPE;
                }
-               if (PRIV(dev)->vcc) return -EBUSY;
+               if (PRIV(dev)->vcc) {
+                       atm_dev_put(dev);
+                       return -EBUSY;
+               }
        }
        else {
                int error;
index f291587d753e1b49ceb6138af1b925801b47a4db..8e0f9256eb5829102b47977ea489e6e03b205fde 100644 (file)
@@ -2834,6 +2834,8 @@ static int cciss_revalidate(struct gendisk *disk)
        InquiryData_struct *inq_buff = NULL;
 
        for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
+               if (!h->drv[logvol])
+                       continue;
                if (memcmp(h->drv[logvol]->LunID, drv->LunID,
                        sizeof(drv->LunID)) == 0) {
                        FOUND = 1;
index 89d8a7cc4054ba627b670a8786e05b1824f5a8b3..24487d4fb20297e6676a91e60c9525f26092e315 100644 (file)
@@ -3627,17 +3627,19 @@ static void drbdd(struct drbd_conf *mdev)
                }
 
                shs = drbd_cmd_handler[cmd].pkt_size - sizeof(union p_header);
-               rv = drbd_recv(mdev, &header->h80.payload, shs);
-               if (unlikely(rv != shs)) {
-                       dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
-                       goto err_out;
-               }
-
                if (packet_size - shs > 0 && !drbd_cmd_handler[cmd].expect_payload) {
                        dev_err(DEV, "No payload expected %s l:%d\n", cmdname(cmd), packet_size);
                        goto err_out;
                }
 
+               if (shs) {
+                       rv = drbd_recv(mdev, &header->h80.payload, shs);
+                       if (unlikely(rv != shs)) {
+                               dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+                               goto err_out;
+                       }
+               }
+
                rv = drbd_cmd_handler[cmd].function(mdev, cmd, packet_size - shs);
 
                if (unlikely(!rv)) {
index 181ea0364822d4f6d559ff1101d95d7d675eff7f..ab2bd09d54b4bfc9fbf7bf74c2e46dbbeb389db5 100644 (file)
@@ -339,7 +339,8 @@ static inline int _req_mod(struct drbd_request *req, enum drbd_req_event what)
 }
 
 /* completion of master bio is outside of spinlock.
- * If you need it irqsave, do it your self! */
+ * If you need it irqsave, do it your self!
+ * Which means: don't use from bio endio callback. */
 static inline int req_mod(struct drbd_request *req,
                enum drbd_req_event what)
 {
index 47d223c2409c8cebbd233103d8ff1790dfae833c..34f224b018b37b1e1781134fedf67179799ab20e 100644 (file)
@@ -193,8 +193,10 @@ void drbd_endio_sec(struct bio *bio, int error)
  */
 void drbd_endio_pri(struct bio *bio, int error)
 {
+       unsigned long flags;
        struct drbd_request *req = bio->bi_private;
        struct drbd_conf *mdev = req->mdev;
+       struct bio_and_error m;
        enum drbd_req_event what;
        int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
@@ -220,7 +222,13 @@ void drbd_endio_pri(struct bio *bio, int error)
        bio_put(req->private_bio);
        req->private_bio = ERR_PTR(error);
 
-       req_mod(req, what);
+       /* not req_mod(), we need irqsave here! */
+       spin_lock_irqsave(&mdev->req_lock, flags);
+       __req_mod(req, what, &m);
+       spin_unlock_irqrestore(&mdev->req_lock, flags);
+
+       if (m.bio)
+               complete_master_bio(mdev, &m);
 }
 
 int w_read_retry_remote(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
index 720148294e648473a1a82cc0c68f50ac1fd923c3..3c6cabcb7d84b0428cdeae91b3f9a98f2bc85715 100644 (file)
@@ -311,8 +311,10 @@ static void hci_uart_tty_close(struct tty_struct *tty)
 
                if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
                        hu->proto->close(hu);
-                       hci_unregister_dev(hdev);
-                       hci_free_dev(hdev);
+                       if (hdev) {
+                               hci_unregister_dev(hdev);
+                               hci_free_dev(hdev);
+                       }
                }
        }
 }
index 16a2847b7cdbfeee43c9dcd212915a2f6b500711..29ac6d499fa6a69221b51ec52ca934c5d41e0912 100644 (file)
@@ -1192,12 +1192,19 @@ static void i9xx_chipset_flush(void)
                writel(1, intel_private.i9xx_flush_page);
 }
 
-static void i965_write_entry(dma_addr_t addr, unsigned int entry,
+static void i965_write_entry(dma_addr_t addr,
+                            unsigned int entry,
                             unsigned int flags)
 {
+       u32 pte_flags;
+
+       pte_flags = I810_PTE_VALID;
+       if (flags == AGP_USER_CACHED_MEMORY)
+               pte_flags |= I830_PTE_SYSTEM_CACHED;
+
        /* Shift high bits down */
        addr |= (addr >> 28) & 0xf0;
-       writel(addr | I810_PTE_VALID, intel_private.gtt + entry);
+       writel(addr | pte_flags, intel_private.gtt + entry);
 }
 
 static bool gen6_check_flags(unsigned int flags)
index 73dcb0ee41fdaebcbefee2b0ddf705bd5a26b1e9..d3d63be2cd37efc15c5b261ab10492ba8b01caf6 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/ramoops.h>
 
 #define RAMOOPS_KERNMSG_HDR "===="
-#define RAMOOPS_HEADER_SIZE   (5 + sizeof(struct timeval))
 
 #define RECORD_SIZE 4096
 
@@ -65,8 +64,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
                        struct ramoops_context, dump);
        unsigned long s1_start, s2_start;
        unsigned long l1_cpy, l2_cpy;
-       int res;
-       char *buf;
+       int res, hdr_size;
+       char *buf, *buf_orig;
        struct timeval timestamp;
 
        /* Only dump oopses if dump_oops is set */
@@ -74,6 +73,8 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
                return;
 
        buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE));
+       buf_orig = buf;
+
        memset(buf, '\0', RECORD_SIZE);
        res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR);
        buf += res;
@@ -81,8 +82,9 @@ static void ramoops_do_dump(struct kmsg_dumper *dumper,
        res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
        buf += res;
 
-       l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE));
-       l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - l2_cpy);
+       hdr_size = buf - buf_orig;
+       l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - hdr_size));
+       l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - hdr_size) - l2_cpy);
 
        s2_start = l2 - l2_cpy;
        s1_start = l1 - l1_cpy;
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
new file mode 100644 (file)
index 0000000..4168c88
--- /dev/null
@@ -0,0 +1,4 @@
+
+config CLKDEV_LOOKUP
+       bool
+       select HAVE_CLK
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
new file mode 100644 (file)
index 0000000..07613fa
--- /dev/null
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_CLKDEV_LOOKUP)    += clkdev.o
similarity index 93%
rename from arch/arm/common/clkdev.c
rename to drivers/clk/clkdev.c
index e2b2bb66e09490e0761c8949cea58f466acb6384..0fc0a79852de0f919bd2ac9ac117533ed8a0f991 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  arch/arm/common/clkdev.c
+ * drivers/clk/clkdev.c
  *
  *  Copyright (C) 2008 Russell King.
  *
 #include <linux/string.h>
 #include <linux/mutex.h>
 #include <linux/clk.h>
-#include <linux/slab.h>
-
-#include <asm/clkdev.h>
-#include <mach/clkdev.h>
+#include <linux/clkdev.h>
 
 static LIST_HEAD(clocks);
 static DEFINE_MUTEX(clocks_mutex);
@@ -120,12 +117,12 @@ struct clk_lookup_alloc {
        char    con_id[MAX_CON_ID];
 };
 
-struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
-       const char *dev_fmt, ...)
+struct clk_lookup * __init_refok
+clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...)
 {
        struct clk_lookup_alloc *cla;
 
-       cla = kzalloc(sizeof(*cla), GFP_KERNEL);
+       cla = __clkdev_alloc(sizeof(*cla));
        if (!cla)
                return NULL;
 
index d68d3aa1814b4ac635017e98cebd9625b0e7b40a..f975d24890fada4fd5db9c920fbc0a5c393d6511 100644 (file)
@@ -283,16 +283,21 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
        } while (delay);
 }
 
-static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+static void __sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
 {
-       unsigned long flags;
-
        if (delta > p->max_match_value)
                dev_warn(&p->pdev->dev, "delta out of range\n");
 
-       spin_lock_irqsave(&p->lock, flags);
        p->next_match_value = delta;
        sh_cmt_clock_event_program_verify(p, 0);
+}
+
+static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&p->lock, flags);
+       __sh_cmt_set_next(p, delta);
        spin_unlock_irqrestore(&p->lock, flags);
 }
 
@@ -359,7 +364,7 @@ static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag)
 
        /* setup timeout if no clockevent */
        if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT)))
-               sh_cmt_set_next(p, p->max_match_value);
+               __sh_cmt_set_next(p, p->max_match_value);
  out:
        spin_unlock_irqrestore(&p->lock, flags);
 
@@ -381,7 +386,7 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag)
 
        /* adjust the timeout to maximum if only clocksource left */
        if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE))
-               sh_cmt_set_next(p, p->max_match_value);
+               __sh_cmt_set_next(p, p->max_match_value);
 
        spin_unlock_irqrestore(&p->lock, flags);
 }
index 411d5bf50fc43cab437dff34d3d9f25dd9928fe0..a25f5f61e0e00becc22b5b5b4d8ce1e4ce6e31b8 100644 (file)
@@ -449,7 +449,7 @@ mv_xor_slot_cleanup(struct mv_xor_chan *mv_chan)
 static void mv_xor_tasklet(unsigned long data)
 {
        struct mv_xor_chan *chan = (struct mv_xor_chan *) data;
-       __mv_xor_slot_cleanup(chan);
+       mv_xor_slot_cleanup(chan);
 }
 
 static struct mv_xor_desc_slot *
index 599f6c9e0fbf18661d7607407d11b73cd3cda7ff..d3e55a0ae92be02e5f46ea7d6f7f82c87e75c807 100644 (file)
@@ -56,15 +56,26 @@ static struct cs5535_gpio_chip {
  * registers, see include/linux/cs5535.h.
  */
 
-static void errata_outl(u32 val, unsigned long addr)
+static void errata_outl(struct cs5535_gpio_chip *chip, u32 val,
+               unsigned int reg)
 {
+       unsigned long addr = chip->base + 0x80 + reg;
+
        /*
         * According to the CS5536 errata (#36), after suspend
         * a write to the high bank GPIO register will clear all
         * non-selected bits; the recommended workaround is a
         * read-modify-write operation.
+        *
+        * Don't apply this errata to the edge status GPIOs, as writing
+        * to their lower bits will clear them.
         */
-       val |= inl(addr);
+       if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) {
+               if (val & 0xffff)
+                       val |= (inl(addr) & 0xffff); /* ignore the high bits */
+               else
+                       val |= (inl(addr) ^ (val >> 16));
+       }
        outl(val, addr);
 }
 
@@ -76,7 +87,7 @@ static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset,
                outl(1 << offset, chip->base + reg);
        else
                /* high bank register */
-               errata_outl(1 << (offset - 16), chip->base + 0x80 + reg);
+               errata_outl(chip, 1 << (offset - 16), reg);
 }
 
 void cs5535_gpio_set(unsigned offset, unsigned int reg)
@@ -98,7 +109,7 @@ static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset,
                outl(1 << (offset + 16), chip->base + reg);
        else
                /* high bank register */
-               errata_outl(1 << offset, chip->base + 0x80 + reg);
+               errata_outl(chip, 1 << offset, reg);
 }
 
 void cs5535_gpio_clear(unsigned offset, unsigned int reg)
index 21da9c19a0cba82e1a8aba6aa52056953efb4f82..649550e2cae99947027df5f2887e77016f554b54 100644 (file)
@@ -1281,6 +1281,9 @@ int gpio_request_one(unsigned gpio, unsigned long flags, const char *label)
                err = gpio_direction_output(gpio,
                                (flags & GPIOF_INIT_HIGH) ? 1 : 0);
 
+       if (err)
+               gpio_free(gpio);
+
        return err;
 }
 EXPORT_SYMBOL_GPL(gpio_request_one);
index 2762698e0204adc99699839137680bafc7fcc0c7..897e0577e65e0fd425f18edb00512ee414566a64 100644 (file)
@@ -135,7 +135,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
        struct rdc321x_gpio *rdc321x_gpio_dev;
        struct rdc321x_gpio_pdata *pdata;
 
-       pdata = pdev->dev.platform_data;
+       pdata = platform_get_drvdata(pdev);
        if (!pdata) {
                dev_err(&pdev->dev, "no platform data supplied\n");
                return -ENODEV;
index bede10a0340700b69717caf1da8e81ee0546ab00..2d4e17a004dbb2f09bae780c56f36138c4b1beca 100644 (file)
@@ -241,7 +241,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
        }
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               if (encoder->crtc && !drm_helper_encoder_in_use(encoder)) {
+               if (!drm_helper_encoder_in_use(encoder)) {
                        drm_encoder_disable(encoder);
                        /* disconnector encoder from any connector */
                        encoder->crtc = NULL;
@@ -874,7 +874,10 @@ static void output_poll_execute(struct work_struct *work)
                        continue;
 
                connector->status = connector->funcs->detect(connector, false);
-               DRM_DEBUG_KMS("connector status updated to %d\n", connector->status);
+               DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %d to %d\n",
+                             connector->base.id,
+                             drm_get_connector_name(connector),
+                             old_status, connector->status);
                if (old_status != connector->status)
                        changed = true;
        }
index af70337567ce35a0167ffb193d8b1ffae769fedd..d3e8c540f778d01ef97437c3643acbd690716546 100644 (file)
@@ -242,7 +242,7 @@ fail:
 
 static enum drm_connector_status ch7017_detect(struct intel_dvo_device *dvo)
 {
-       return connector_status_unknown;
+       return connector_status_connected;
 }
 
 static enum drm_mode_status ch7017_mode_valid(struct intel_dvo_device *dvo,
index e6800819bca846f6a3fd102ef37e2632858247f8..cb900dc83d950e29f99144e0d39c38102c55ce5b 100644 (file)
@@ -34,6 +34,7 @@
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "i915_trace.h"
+#include "../../../platform/x86/intel_ips.h"
 #include <linux/pci.h>
 #include <linux/vgaarb.h>
 #include <linux/acpi.h>
@@ -1870,6 +1871,26 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(i915_gpu_turbo_disable);
 
+/**
+ * Tells the intel_ips driver that the i915 driver is now loaded, if
+ * IPS got loaded first.
+ *
+ * This awkward dance is so that neither module has to depend on the
+ * other in order for IPS to do the appropriate communication of
+ * GPU turbo limits to i915.
+ */
+static void
+ips_ping_for_i915_load(void)
+{
+       void (*link)(void);
+
+       link = symbol_get(ips_link_to_i915_driver);
+       if (link) {
+               link();
+               symbol_put(ips_link_to_i915_driver);
+       }
+}
+
 /**
  * i915_driver_load - setup chip and create an initial config
  * @dev: DRM device
@@ -2075,6 +2096,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        dev_priv->mchdev_lock = &mchdev_lock;
        spin_unlock(&mchdev_lock);
 
+       ips_ping_for_i915_load();
+
        return 0;
 
 out_workqueue_free:
index 878fc766a12cc05f6b30c90d53d65a52c6023727..cb8f434292793451225eefdbea071aefe7408e79 100644 (file)
 # define MARIUNIT_CLOCK_GATE_DISABLE           (1 << 18)
 # define SVSMUNIT_CLOCK_GATE_DISABLE           (1 << 1)
 
+#define PCH_3DCGDIS1           0x46024
+# define VFMUNIT_CLOCK_GATE_DISABLE            (1 << 11)
+
 #define FDI_PLL_FREQ_CTL        0x46030
 #define  FDI_PLL_FREQ_CHANGE_REQUEST    (1<<24)
 #define  FDI_PLL_FREQ_LOCK_LIMIT_MASK   0xfff00
 #define ILK_DISPLAY_CHICKEN2   0x42004
 #define  ILK_DPARB_GATE        (1<<22)
 #define  ILK_VSDPFD_FULL       (1<<21)
+#define ILK_DISPLAY_CHICKEN_FUSES      0x42014
+#define  ILK_INTERNAL_GRAPHICS_DISABLE (1<<31)
+#define  ILK_INTERNAL_DISPLAY_DISABLE  (1<<30)
+#define  ILK_DISPLAY_DEBUG_DISABLE     (1<<29)
+#define  ILK_HDCP_DISABLE              (1<<25)
+#define  ILK_eDP_A_DISABLE             (1<<24)
+#define  ILK_DESKTOP                   (1<<23)
 #define ILK_DSPCLK_GATE                0x42020
 #define  ILK_DPARB_CLK_GATE    (1<<5)
 /* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */
index d9b7092439ef59ab19acc9546a039ff60f0bb43c..fca523288acad035b9f3d130fe32e9c3c7719989 100644 (file)
@@ -5379,6 +5379,23 @@ static int intel_encoder_clones(struct drm_device *dev, int type_mask)
        return index_mask;
 }
 
+static bool has_edp_a(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (!IS_MOBILE(dev))
+               return false;
+
+       if ((I915_READ(DP_A) & DP_DETECTED) == 0)
+               return false;
+
+       if (IS_GEN5(dev) &&
+           (I915_READ(ILK_DISPLAY_CHICKEN_FUSES) & ILK_eDP_A_DISABLE))
+               return false;
+
+       return true;
+}
+
 static void intel_setup_outputs(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -5396,7 +5413,7 @@ static void intel_setup_outputs(struct drm_device *dev)
        if (HAS_PCH_SPLIT(dev)) {
                dpd_is_edp = intel_dpd_is_edp(dev);
 
-               if (IS_MOBILE(dev) && (I915_READ(DP_A) & DP_DETECTED))
+               if (has_edp_a(dev))
                        intel_dp_init(dev, DP_A);
 
                if (dpd_is_edp && (I915_READ(PCH_DP_D) & DP_DETECTED))
@@ -5825,6 +5842,8 @@ void intel_init_clock_gating(struct drm_device *dev)
                        I915_WRITE(PCH_3DCGDIS0,
                                   MARIUNIT_CLOCK_GATE_DISABLE |
                                   SVSMUNIT_CLOCK_GATE_DISABLE);
+                       I915_WRITE(PCH_3DCGDIS1,
+                                  VFMUNIT_CLOCK_GATE_DISABLE);
                }
 
                I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate);
index df648cb4c29641cec581307b1c40a46d812fd58b..864417cffe9a7c3a45ea52716aae46da97e1b7c1 100644 (file)
@@ -479,6 +479,7 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
        uint16_t address = algo_data->address;
        uint8_t msg[5];
        uint8_t reply[2];
+       unsigned retry;
        int msg_bytes;
        int reply_bytes;
        int ret;
@@ -513,14 +514,33 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                break;
        }
 
-       for (;;) {
-         ret = intel_dp_aux_ch(intel_dp,
-                               msg, msg_bytes,
-                               reply, reply_bytes);
+       for (retry = 0; retry < 5; retry++) {
+               ret = intel_dp_aux_ch(intel_dp,
+                                     msg, msg_bytes,
+                                     reply, reply_bytes);
                if (ret < 0) {
                        DRM_DEBUG_KMS("aux_ch failed %d\n", ret);
                        return ret;
                }
+
+               switch (reply[0] & AUX_NATIVE_REPLY_MASK) {
+               case AUX_NATIVE_REPLY_ACK:
+                       /* I2C-over-AUX Reply field is only valid
+                        * when paired with AUX ACK.
+                        */
+                       break;
+               case AUX_NATIVE_REPLY_NACK:
+                       DRM_DEBUG_KMS("aux_ch native nack\n");
+                       return -EREMOTEIO;
+               case AUX_NATIVE_REPLY_DEFER:
+                       udelay(100);
+                       continue;
+               default:
+                       DRM_ERROR("aux_ch invalid native reply 0x%02x\n",
+                                 reply[0]);
+                       return -EREMOTEIO;
+               }
+
                switch (reply[0] & AUX_I2C_REPLY_MASK) {
                case AUX_I2C_REPLY_ACK:
                        if (mode == MODE_I2C_READ) {
@@ -528,17 +548,20 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                        }
                        return reply_bytes - 1;
                case AUX_I2C_REPLY_NACK:
-                       DRM_DEBUG_KMS("aux_ch nack\n");
+                       DRM_DEBUG_KMS("aux_i2c nack\n");
                        return -EREMOTEIO;
                case AUX_I2C_REPLY_DEFER:
-                       DRM_DEBUG_KMS("aux_ch defer\n");
+                       DRM_DEBUG_KMS("aux_i2c defer\n");
                        udelay(100);
                        break;
                default:
-                       DRM_ERROR("aux_ch invalid reply 0x%02x\n", reply[0]);
+                       DRM_ERROR("aux_i2c invalid reply 0x%02x\n", reply[0]);
                        return -EREMOTEIO;
                }
        }
+
+       DRM_ERROR("too many retries, giving up\n");
+       return -EREMOTEIO;
 }
 
 static int
index 89a65be8a3f364359edaf6add71b6259affa3cbd..31cd7e33e8208b8112ed7cb2b278e8cc8b84fc61 100644 (file)
@@ -696,20 +696,17 @@ int intel_wait_ring_buffer(struct drm_device *dev,
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 head;
 
-       head = intel_read_status_page(ring, 4);
-       if (head) {
-               ring->head = head & HEAD_ADDR;
-               ring->space = ring->head - (ring->tail + 8);
-               if (ring->space < 0)
-                       ring->space += ring->size;
-               if (ring->space >= n)
-                       return 0;
-       }
-
        trace_i915_ring_wait_begin (dev);
        end = jiffies + 3 * HZ;
        do {
-               ring->head = I915_READ_HEAD(ring) & HEAD_ADDR;
+               /* If the reported head position has wrapped or hasn't advanced,
+                * fallback to the slow and accurate path.
+                */
+               head = intel_read_status_page(ring, 4);
+               if (head < ring->actual_head)
+                       head = I915_READ_HEAD(ring);
+               ring->actual_head = head;
+               ring->head = head & HEAD_ADDR;
                ring->space = ring->head - (ring->tail + 8);
                if (ring->space < 0)
                        ring->space += ring->size;
index 3126c2681983e21ba729d9ca599d104f4f1323de..d2cd0f1efeedfdec3102f0436dc70d0d47a2d52d 100644 (file)
@@ -30,8 +30,9 @@ struct  intel_ring_buffer {
        struct          drm_device *dev;
        struct          drm_gem_object *gem_object;
 
-       unsigned int    head;
-       unsigned int    tail;
+       u32             actual_head;
+       u32             head;
+       u32             tail;
        int             space;
        struct intel_hw_status_page status_page;
 
index d97e6cb52d34a102705d9ab59f030cb551333e16..6bc42fa2a6ecc152d796611a3e66311b98b3de9f 100644 (file)
@@ -1908,9 +1908,12 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
                speed = mapping->i2c_speed;
        }
 
-       sdvo->i2c = &dev_priv->gmbus[pin].adapter;
-       intel_gmbus_set_speed(sdvo->i2c, speed);
-       intel_gmbus_force_bit(sdvo->i2c, true);
+       if (pin < GMBUS_NUM_PORTS) {
+               sdvo->i2c = &dev_priv->gmbus[pin].adapter;
+               intel_gmbus_set_speed(sdvo->i2c, speed);
+               intel_gmbus_force_bit(sdvo->i2c, true);
+       } else
+               sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter;
 }
 
 static bool
@@ -2037,13 +2040,14 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
                                           SDVO_COLORIMETRY_RGB256);
                connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
 
-               intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
                intel_sdvo->is_hdmi = true;
        }
        intel_sdvo->base.clone_mask = ((1 << INTEL_SDVO_NON_TV_CLONE_BIT) |
                                       (1 << INTEL_ANALOG_CLONE_BIT));
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
+       if (intel_sdvo->is_hdmi)
+               intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
 
        return true;
 }
index df2b6f2b35f893d00b475147f8d995a7b3c15bc2..9fbabaa6ee448bb665766a34dc944c694e69eaa3 100644 (file)
@@ -253,7 +253,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
                drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
-               atombios_blank_crtc(crtc, ATOM_ENABLE);
+               if (radeon_crtc->enabled)
+                       atombios_blank_crtc(crtc, ATOM_ENABLE);
                if (ASIC_IS_DCE3(rdev))
                        atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
                atombios_enable_crtc(crtc, ATOM_DISABLE);
@@ -530,7 +531,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                        dp_clock = dig_connector->dp_clock;
                                }
                        }
-
+#if 0 /* doesn't work properly on some laptops */
                        /* use recommended ref_div for ss */
                        if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
                                if (ss_enabled) {
@@ -540,7 +541,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                        }
                                }
                        }
-
+#endif
                        if (ASIC_IS_AVIVO(rdev)) {
                                /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
                                if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
index 4dc5b4714c5a6ae1919246ac55ed32d3bacc44ac..7b337c361a1240f12afc0105bc55d0867172b151 100644 (file)
@@ -748,6 +748,8 @@ void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev)
        unsigned i;
        u32 tmp;
 
+       WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+
        WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1));
        for (i = 0; i < rdev->usec_timeout; i++) {
                /* read MC_STATUS */
@@ -1922,7 +1924,6 @@ bool evergreen_gpu_is_lockup(struct radeon_device *rdev)
 static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
 {
        struct evergreen_mc_save save;
-       u32 srbm_reset = 0;
        u32 grbm_reset = 0;
 
        dev_info(rdev->dev, "GPU softreset \n");
@@ -1961,16 +1962,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
        udelay(50);
        WREG32(GRBM_SOFT_RESET, 0);
        (void)RREG32(GRBM_SOFT_RESET);
-
-       /* reset all the system blocks */
-       srbm_reset = SRBM_SOFT_RESET_ALL_MASK;
-
-       dev_info(rdev->dev, "  SRBM_SOFT_RESET=0x%08X\n", srbm_reset);
-       WREG32(SRBM_SOFT_RESET, srbm_reset);
-       (void)RREG32(SRBM_SOFT_RESET);
-       udelay(50);
-       WREG32(SRBM_SOFT_RESET, 0);
-       (void)RREG32(SRBM_SOFT_RESET);
        /* Wait a little for things to settle down */
        udelay(50);
        dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
@@ -1981,10 +1972,6 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev)
                RREG32(GRBM_STATUS_SE1));
        dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
                RREG32(SRBM_STATUS));
-       /* After reset we need to reinit the asic as GPU often endup in an
-        * incoherent state.
-        */
-       atom_asic_init(rdev->mode_info.atom_context);
        evergreen_mc_resume(rdev, &save);
        return 0;
 }
@@ -2596,6 +2583,11 @@ int evergreen_resume(struct radeon_device *rdev)
 {
        int r;
 
+       /* reset the asic, the gfx blocks are often in a bad state
+        * after the driver is unloaded or after a resume
+        */
+       if (radeon_asic_reset(rdev))
+               dev_warn(rdev->dev, "GPU reset failed !\n");
        /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
         * posting will perform necessary task to bring back GPU into good
         * shape.
@@ -2712,6 +2704,11 @@ int evergreen_init(struct radeon_device *rdev)
        r = radeon_atombios_init(rdev);
        if (r)
                return r;
+       /* reset the asic, the gfx blocks are often in a bad state
+        * after the driver is unloaded or after a resume
+        */
+       if (radeon_asic_reset(rdev))
+               dev_warn(rdev->dev, "GPU reset failed !\n");
        /* Post card if necessary */
        if (!evergreen_card_posted(rdev)) {
                if (!rdev->bios) {
index 113c70cc8b3930eba7170a94f2c75b9f62e07c1d..a73b53c44359c59a617c6c7aed5a8510a40c39d2 100644 (file)
 #define        HDP_NONSURFACE_BASE                             0x2C04
 #define        HDP_NONSURFACE_INFO                             0x2C08
 #define        HDP_NONSURFACE_SIZE                             0x2C0C
+#define HDP_MEM_COHERENCY_FLUSH_CNTL                   0x5480
 #define HDP_REG_COHERENCY_FLUSH_CNTL                   0x54A0
 #define        HDP_TILING_CONFIG                               0x2F3C
 
index 4d7a2e1bdb90e498138eea542e22884c9e36eb0d..9c92db7c896b6719edfaef92d1484ca300d2cb95 100644 (file)
@@ -1342,13 +1342,19 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev)
        u32 srbm_status;
        u32 grbm_status;
        u32 grbm_status2;
+       struct r100_gpu_lockup *lockup;
        int r;
 
+       if (rdev->family >= CHIP_RV770)
+               lockup = &rdev->config.rv770.lockup;
+       else
+               lockup = &rdev->config.r600.lockup;
+
        srbm_status = RREG32(R_000E50_SRBM_STATUS);
        grbm_status = RREG32(R_008010_GRBM_STATUS);
        grbm_status2 = RREG32(R_008014_GRBM_STATUS2);
        if (!G_008010_GUI_ACTIVE(grbm_status)) {
-               r100_gpu_lockup_update(&rdev->config.r300.lockup, &rdev->cp);
+               r100_gpu_lockup_update(lockup, &rdev->cp);
                return false;
        }
        /* force CP activities */
@@ -1360,7 +1366,7 @@ bool r600_gpu_is_lockup(struct radeon_device *rdev)
                radeon_ring_unlock_commit(rdev);
        }
        rdev->cp.rptr = RREG32(R600_CP_RB_RPTR);
-       return r100_gpu_cp_is_lockup(rdev, &rdev->config.r300.lockup, &rdev->cp);
+       return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp);
 }
 
 int r600_asic_reset(struct radeon_device *rdev)
index 0f90fc3482ce205df9991bcd1d7c1170abd912ca..7831e0890210c6b4b7a80f09da51d7b76cc80511 100644 (file)
@@ -315,11 +315,10 @@ static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
                if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
                        /* the initial DDX does bad things with the CB size occasionally */
                        /* it rounds up height too far for slice tile max but the BO is smaller */
-                       tmp = (height - 7) * 8 * bpe;
-                       if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
-                               dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
-                               return -EINVAL;
-                       }
+                       /* r600c,g also seem to flush at bad times in some apps resulting in
+                        * bogus values here. So for linear just allow anything to avoid breaking
+                        * broken userspace.
+                        */
                } else {
                        dev_warn(p->dev, "%s offset[%d] %d %d %lu too big\n", __func__, i, track->cb_color_bo_offset[i], tmp, radeon_bo_size(track->cb_color_bo[i]));
                        return -EINVAL;
index e12e79326cb115a490ed5d94e0eda2a84ee400db..501966a13f48094a65cfeb17460fa16aeb62a308 100644 (file)
@@ -910,11 +910,6 @@ int radeon_resume_kms(struct drm_device *dev)
        radeon_pm_resume(rdev);
        radeon_restore_bios_scratch_regs(rdev);
 
-       /* turn on display hw */
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-               drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
-       }
-
        radeon_fbdev_set_suspend(rdev, 0);
        release_console_sem();
 
@@ -922,6 +917,10 @@ int radeon_resume_kms(struct drm_device *dev)
        radeon_hpd_init(rdev);
        /* blat the mode back in */
        drm_helper_resume_force_mode(dev);
+       /* turn on display hw */
+       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+               drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
+       }
        return 0;
 }
 
index 88e4ea925900ef3aecf71aa17744d3f9d0d8c445..60e689f2d048b71aa85b2a95d759fab06352250c 100644 (file)
@@ -232,9 +232,28 @@ static struct drm_driver driver_old = {
 
 static struct drm_driver kms_driver;
 
+static void radeon_kick_out_firmware_fb(struct pci_dev *pdev)
+{
+       struct apertures_struct *ap;
+       bool primary = false;
+
+       ap = alloc_apertures(1);
+       ap->ranges[0].base = pci_resource_start(pdev, 0);
+       ap->ranges[0].size = pci_resource_len(pdev, 0);
+
+#ifdef CONFIG_X86
+       primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
+#endif
+       remove_conflicting_framebuffers(ap, "radeondrmfb", primary);
+       kfree(ap);
+}
+
 static int __devinit
 radeon_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
+       /* Get rid of things like offb */
+       radeon_kick_out_firmware_fb(pdev);
+
        return drm_get_pci_dev(pdev, ent, &kms_driver);
 }
 
index efa211898fe60204a424b98cdb9295ea2ee99356..6abea32be5e83b80346f5c79b0a966c66c194a7c 100644 (file)
@@ -245,7 +245,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
                goto out_unref;
        }
        info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
-       info->apertures->ranges[0].size = rdev->mc.real_vram_size;
+       info->apertures->ranges[0].size = rdev->mc.aper_size;
 
        info->fix.mmio_start = 0;
        info->fix.mmio_len = 0;
index 05248f2d7581cd02dc191185b083bd30977ec5ba..92b42db43bcfd9e5706c41bfb9049a26fd967b93 100644 (file)
@@ -234,7 +234,6 @@ static int s3c_hwmon_create_attr(struct device *dev,
        attr->index = channel;
        attr->dev_attr.attr.name  = attrs->in_name;
        attr->dev_attr.attr.mode  = S_IRUGO;
-       attr->dev_attr.attr.owner = THIS_MODULE;
        attr->dev_attr.show = s3c_hwmon_ch_show;
 
        ret =  device_create_file(dev, &attr->dev_attr);
@@ -252,7 +251,6 @@ static int s3c_hwmon_create_attr(struct device *dev,
                attr->index = channel;
                attr->dev_attr.attr.name  = attrs->label_name;
                attr->dev_attr.attr.mode  = S_IRUGO;
-               attr->dev_attr.attr.owner = THIS_MODULE;
                attr->dev_attr.show = s3c_hwmon_label_show;
 
                ret = device_create_file(dev, &attr->dev_attr);
index e3f7fc6f95657e2f4846cebc0efae905d309c31d..68f09a868434b52a6522c147dce8125f42f6505f 100644 (file)
@@ -534,76 +534,73 @@ static int handle_eviocgbit(struct input_dev *dev,
 }
 #undef OLD_KEY_MAX
 
-static int evdev_handle_get_keycode(struct input_dev *dev,
-                                   void __user *p, size_t size)
+static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p)
 {
-       struct input_keymap_entry ke;
+       struct input_keymap_entry ke = {
+               .len    = sizeof(unsigned int),
+               .flags  = 0,
+       };
+       int __user *ip = (int __user *)p;
        int error;
 
-       memset(&ke, 0, sizeof(ke));
-
-       if (size == sizeof(unsigned int[2])) {
-               /* legacy case */
-               int __user *ip = (int __user *)p;
+       /* legacy case */
+       if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+               return -EFAULT;
 
-               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
-                       return -EFAULT;
+       error = input_get_keycode(dev, &ke);
+       if (error)
+               return error;
 
-               ke.len = sizeof(unsigned int);
-               ke.flags = 0;
+       if (put_user(ke.keycode, ip + 1))
+               return -EFAULT;
 
-               error = input_get_keycode(dev, &ke);
-               if (error)
-                       return error;
+       return 0;
+}
 
-               if (put_user(ke.keycode, ip + 1))
-                       return -EFAULT;
+static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p)
+{
+       struct input_keymap_entry ke;
+       int error;
 
-       } else {
-               size = min(size, sizeof(ke));
+       if (copy_from_user(&ke, p, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_from_user(&ke, p, size))
-                       return -EFAULT;
+       error = input_get_keycode(dev, &ke);
+       if (error)
+               return error;
 
-               error = input_get_keycode(dev, &ke);
-               if (error)
-                       return error;
+       if (copy_to_user(p, &ke, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_to_user(p, &ke, size))
-                       return -EFAULT;
-       }
        return 0;
 }
 
-static int evdev_handle_set_keycode(struct input_dev *dev,
-                                   void __user *p, size_t size)
+static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p)
 {
-       struct input_keymap_entry ke;
-
-       memset(&ke, 0, sizeof(ke));
+       struct input_keymap_entry ke = {
+               .len    = sizeof(unsigned int),
+               .flags  = 0,
+       };
+       int __user *ip = (int __user *)p;
 
-       if (size == sizeof(unsigned int[2])) {
-               /* legacy case */
-               int __user *ip = (int __user *)p;
+       if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
+               return -EFAULT;
 
-               if (copy_from_user(ke.scancode, p, sizeof(unsigned int)))
-                       return -EFAULT;
+       if (get_user(ke.keycode, ip + 1))
+               return -EFAULT;
 
-               if (get_user(ke.keycode, ip + 1))
-                       return -EFAULT;
+       return input_set_keycode(dev, &ke);
+}
 
-               ke.len = sizeof(unsigned int);
-               ke.flags = 0;
+static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p)
+{
+       struct input_keymap_entry ke;
 
-       } else {
-               size = min(size, sizeof(ke));
+       if (copy_from_user(&ke, p, sizeof(ke)))
+               return -EFAULT;
 
-               if (copy_from_user(&ke, p, size))
-                       return -EFAULT;
-
-               if (ke.len > sizeof(ke.scancode))
-                       return -EINVAL;
-       }
+       if (ke.len > sizeof(ke.scancode))
+               return -EINVAL;
 
        return input_set_keycode(dev, &ke);
 }
@@ -669,6 +666,18 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return evdev_grab(evdev, client);
                else
                        return evdev_ungrab(evdev, client);
+
+       case EVIOCGKEYCODE:
+               return evdev_handle_get_keycode(dev, p);
+
+       case EVIOCSKEYCODE:
+               return evdev_handle_set_keycode(dev, p);
+
+       case EVIOCGKEYCODE_V2:
+               return evdev_handle_get_keycode_v2(dev, p);
+
+       case EVIOCSKEYCODE_V2:
+               return evdev_handle_set_keycode_v2(dev, p);
        }
 
        size = _IOC_SIZE(cmd);
@@ -708,12 +717,6 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
                        return -EFAULT;
 
                return error;
-
-       case EVIOC_MASK_SIZE(EVIOCGKEYCODE):
-               return evdev_handle_get_keycode(dev, p, size);
-
-       case EVIOC_MASK_SIZE(EVIOCSKEYCODE):
-               return evdev_handle_set_keycode(dev, p, size);
        }
 
        /* Multi-number variable-length handlers */
index 4852b440960abadea47ab158dc8e6e6140970b06..435b0af401e46e38b23fd6ffba9e862f90c9729b 100644 (file)
@@ -1436,6 +1436,8 @@ static struct wacom_features wacom_features_0xD2 =
        { "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD3 =
        { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
+static const struct wacom_features wacom_features_0xD4 =
+       { "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xD8 =
        { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };
 static struct wacom_features wacom_features_0xDA =
@@ -1510,6 +1512,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xD1) },
        { USB_DEVICE_WACOM(0xD2) },
        { USB_DEVICE_WACOM(0xD3) },
+       { USB_DEVICE_WACOM(0xD4) },
        { USB_DEVICE_WACOM(0xD8) },
        { USB_DEVICE_WACOM(0xDA) },
        { USB_DEVICE_WACOM(0xDB) },
index bcc174e4f3b146db6772cea89c79ac9eb14ce80a..658e75f18d052b5a721ff2e6882109c945318d5b 100644 (file)
@@ -1900,6 +1900,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif,
                if (b3skb == NULL) {
                        dev_err(cs->dev, "%s: out of memory\n", __func__);
                        send_conf(iif, ap, skb, CAPI_MSGOSRESOURCEERR);
+                       kfree(b3cmsg);
                        return;
                }
                capi_cmsg2message(b3cmsg,
index 211e21f34bd57d5f6e2b079dcd22194713b3d5f5..d5a4ade88991eb690e053a6a4218de0512ad9387 100644 (file)
@@ -267,7 +267,7 @@ void led_blink_set(struct led_classdev *led_cdev,
                   unsigned long *delay_off)
 {
        if (led_cdev->blink_set &&
-           led_cdev->blink_set(led_cdev, delay_on, delay_off))
+           !led_cdev->blink_set(led_cdev, delay_on, delay_off))
                return;
 
        /* blink with 1 Hz as default if nothing specified */
index 90267f8d64eeadf5d9e72afae174f6d4b22e6bf5..4d705cea0f8c74c4010e7fe6fbf8d77288f49c36 100644 (file)
@@ -517,9 +517,8 @@ int dm_set_device_limits(struct dm_target *ti, struct dm_dev *dev,
         */
 
        if (q->merge_bvec_fn && !ti->type->merge)
-               limits->max_sectors =
-                       min_not_zero(limits->max_sectors,
-                                    (unsigned int) (PAGE_SIZE >> 9));
+               blk_limits_max_hw_sectors(limits,
+                                         (unsigned int) (PAGE_SIZE >> 9));
        return 0;
 }
 EXPORT_SYMBOL_GPL(dm_set_device_limits);
@@ -1131,11 +1130,6 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
         */
        q->limits = *limits;
 
-       if (limits->no_cluster)
-               queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
-       else
-               queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
-
        if (!dm_table_supports_discards(t))
                queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
        else
index e71c5fa527f59ec3e6ea5fd6ce7d09746bfc437e..175c424f201f33caa0c50525a41b7f8fc3569387 100644 (file)
@@ -4295,9 +4295,6 @@ static int md_alloc(dev_t dev, char *name)
                goto abort;
        mddev->queue->queuedata = mddev;
 
-       /* Can be unlocked because the queue is new: no concurrency */
-       queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue);
-
        blk_queue_make_request(mddev->queue, md_make_request);
 
        disk = alloc_disk(1 << shift);
index 1b7adabbcee99d4affc24f48e335f33cb3dd409e..6da955dfef48989a1773792f09bf1715326a86b5 100644 (file)
@@ -26,8 +26,8 @@ static struct ir_scancode rc6_mce[] = {
 
        { 0x800f040a, KEY_DELETE },
        { 0x800f040b, KEY_ENTER },
-       { 0x800f040c, KEY_POWER },
-       { 0x800f040d, KEY_PROG1 },              /* Windows MCE button */
+       { 0x800f040c, KEY_POWER },              /* PC Power */
+       { 0x800f040d, KEY_PROG1 },              /* Windows MCE button */
        { 0x800f040e, KEY_MUTE },
        { 0x800f040f, KEY_INFO },
 
@@ -56,31 +56,32 @@ static struct ir_scancode rc6_mce[] = {
        { 0x800f0422, KEY_OK },
        { 0x800f0423, KEY_EXIT },
        { 0x800f0424, KEY_DVD },
-       { 0x800f0425, KEY_TUNER },              /* LiveTV */
-       { 0x800f0426, KEY_EPG },                /* Guide */
-       { 0x800f0427, KEY_ZOOM },               /* Aspect */
+       { 0x800f0425, KEY_TUNER },              /* LiveTV */
+       { 0x800f0426, KEY_EPG },                /* Guide */
+       { 0x800f0427, KEY_ZOOM },               /* Aspect */
 
        { 0x800f043a, KEY_BRIGHTNESSUP },
 
        { 0x800f0446, KEY_TV },
-       { 0x800f0447, KEY_AUDIO },              /* My Music */
-       { 0x800f0448, KEY_PVR },                /* RecordedTV */
+       { 0x800f0447, KEY_AUDIO },              /* My Music */
+       { 0x800f0448, KEY_PVR },                /* RecordedTV */
        { 0x800f0449, KEY_CAMERA },
        { 0x800f044a, KEY_VIDEO },
        { 0x800f044c, KEY_LANGUAGE },
        { 0x800f044d, KEY_TITLE },
-       { 0x800f044e, KEY_PRINT },      /* Print - HP OEM version of remote */
+       { 0x800f044e, KEY_PRINT },      /* Print - HP OEM version of remote */
 
        { 0x800f0450, KEY_RADIO },
 
-       { 0x800f045a, KEY_SUBTITLE },           /* Caption/Teletext */
+       { 0x800f045a, KEY_SUBTITLE },           /* Caption/Teletext */
        { 0x800f045b, KEY_RED },
        { 0x800f045c, KEY_GREEN },
        { 0x800f045d, KEY_YELLOW },
        { 0x800f045e, KEY_BLUE },
 
+       { 0x800f0465, KEY_POWER2 },     /* TV Power */
        { 0x800f046e, KEY_PLAYPAUSE },
-       { 0x800f046f, KEY_MEDIA },      /* Start media application (NEW) */
+       { 0x800f046f, KEY_MEDIA },      /* Start media application (NEW) */
 
        { 0x800f0480, KEY_BRIGHTNESSDOWN },
        { 0x800f0481, KEY_PLAYPAUSE },
index 8418b14ee4d2244ee3b6528549d0d22f35c85159..756656e17bddb035dbff24529155a86e82d19b3c 100644 (file)
@@ -522,10 +522,8 @@ unsigned int lirc_dev_fop_poll(struct file *file, poll_table *wait)
 
        dev_dbg(ir->d.dev, LOGHEAD "poll called\n", ir->d.name, ir->d.minor);
 
-       if (!ir->attached) {
-               mutex_unlock(&ir->irctl_lock);
+       if (!ir->attached)
                return POLLERR;
-       }
 
        poll_wait(file, &ir->buf->wait_poll, wait);
 
@@ -649,18 +647,18 @@ ssize_t lirc_dev_fop_read(struct file *file,
        if (!buf)
                return -ENOMEM;
 
-       if (mutex_lock_interruptible(&ir->irctl_lock))
-               return -ERESTARTSYS;
+       if (mutex_lock_interruptible(&ir->irctl_lock)) {
+               ret = -ERESTARTSYS;
+               goto out_unlocked;
+       }
        if (!ir->attached) {
-               mutex_unlock(&ir->irctl_lock);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto out_locked;
        }
 
        if (length % ir->chunk_size) {
-               dev_dbg(ir->d.dev, LOGHEAD "read result = -EINVAL\n",
-                       ir->d.name, ir->d.minor);
-               mutex_unlock(&ir->irctl_lock);
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out_locked;
        }
 
        /*
@@ -711,18 +709,23 @@ ssize_t lirc_dev_fop_read(struct file *file,
                        lirc_buffer_read(ir->buf, buf);
                        ret = copy_to_user((void *)buffer+written, buf,
                                           ir->buf->chunk_size);
-                       written += ir->buf->chunk_size;
+                       if (!ret)
+                               written += ir->buf->chunk_size;
+                       else
+                               ret = -EFAULT;
                }
        }
 
        remove_wait_queue(&ir->buf->wait_poll, &wait);
        set_current_state(TASK_RUNNING);
+
+out_locked:
        mutex_unlock(&ir->irctl_lock);
 
 out_unlocked:
        kfree(buf);
        dev_dbg(ir->d.dev, LOGHEAD "read result = %s (%d)\n",
-               ir->d.name, ir->d.minor, ret ? "-EFAULT" : "OK", ret);
+               ir->d.name, ir->d.minor, ret ? "<fail>" : "<ok>", ret);
 
        return ret ? ret : written;
 }
index 9dce684fd23113d13a3d445995983089cff56c60..392ca24132dafd5456e905fa61c216d566703976 100644 (file)
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
 #include <media/ir-core.h>
-#include <media/ir-common.h>
 
 #define DRIVER_VERSION "1.91"
 #define DRIVER_AUTHOR  "Jarod Wilson <jarod@wilsonet.com>"
@@ -49,6 +49,7 @@
 #define USB_BUFLEN             32 /* USB reception buffer length */
 #define USB_CTRL_MSG_SZ                2  /* Size of usb ctrl msg on gen1 hw */
 #define MCE_G1_INIT_MSGS       40 /* Init messages on gen1 hw to throw out */
+#define MS_TO_NS(msec)         ((msec) * 1000)
 
 /* MCE constants */
 #define MCE_CMDBUF_SIZE                384  /* MCE Command buffer length */
@@ -74,6 +75,7 @@
 #define MCE_PACKET_LENGTH_MASK 0x1f /* Packet length mask */
 
 /* Sub-commands, which follow MCE_COMMAND_HEADER or MCE_HW_CMD_HEADER */
+#define MCE_CMD_SIG_END                0x01    /* End of signal */
 #define MCE_CMD_PING           0x03    /* Ping device */
 #define MCE_CMD_UNKNOWN                0x04    /* Unknown */
 #define MCE_CMD_UNKNOWN2       0x05    /* Unknown */
@@ -91,6 +93,7 @@
 #define MCE_CMD_G_TXMASK       0x13    /* Set TX port bitmask */
 #define MCE_CMD_S_RXSENSOR     0x14    /* Set RX sensor (std/learning) */
 #define MCE_CMD_G_RXSENSOR     0x15    /* Get RX sensor (std/learning) */
+#define MCE_RSP_PULSE_COUNT    0x15    /* RX pulse count (only if learning) */
 #define MCE_CMD_TX_PORTS       0x16    /* Get number of TX ports */
 #define MCE_CMD_G_WAKESRC      0x17    /* Get wake source */
 #define MCE_CMD_UNKNOWN7       0x18    /* Unknown */
@@ -146,14 +149,16 @@ enum mceusb_model_type {
        MCE_GEN3,
        MCE_GEN2_TX_INV,
        POLARIS_EVK,
+       CX_HYBRID_TV,
 };
 
 struct mceusb_model {
        u32 mce_gen1:1;
        u32 mce_gen2:1;
        u32 mce_gen3:1;
-       u32 tx_mask_inverted:1;
+       u32 tx_mask_normal:1;
        u32 is_polaris:1;
+       u32 no_tx:1;
 
        const char *rc_map;     /* Allow specify a per-board map */
        const char *name;       /* per-board name */
@@ -162,18 +167,18 @@ struct mceusb_model {
 static const struct mceusb_model mceusb_model[] = {
        [MCE_GEN1] = {
                .mce_gen1 = 1,
-               .tx_mask_inverted = 1,
+               .tx_mask_normal = 1,
        },
        [MCE_GEN2] = {
                .mce_gen2 = 1,
        },
        [MCE_GEN2_TX_INV] = {
                .mce_gen2 = 1,
-               .tx_mask_inverted = 1,
+               .tx_mask_normal = 1,
        },
        [MCE_GEN3] = {
                .mce_gen3 = 1,
-               .tx_mask_inverted = 1,
+               .tx_mask_normal = 1,
        },
        [POLARIS_EVK] = {
                .is_polaris = 1,
@@ -183,7 +188,12 @@ static const struct mceusb_model mceusb_model[] = {
                 * to allow testing it
                 */
                .rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
-               .name = "cx231xx MCE IR",
+               .name = "Conexant Hybrid TV (cx231xx) MCE IR",
+       },
+       [CX_HYBRID_TV] = {
+               .is_polaris = 1,
+               .no_tx = 1, /* tx isn't wired up at all */
+               .name = "Conexant Hybrid TV (cx231xx) MCE IR",
        },
 };
 
@@ -273,6 +283,8 @@ static struct usb_device_id mceusb_dev_table[] = {
        { USB_DEVICE(VENDOR_FORMOSA, 0xe03c) },
        /* Formosa Industrial Computing */
        { USB_DEVICE(VENDOR_FORMOSA, 0xe03e) },
+       /* Fintek eHome Infrared Transceiver (HP branded) */
+       { USB_DEVICE(VENDOR_FINTEK, 0x5168) },
        /* Fintek eHome Infrared Transceiver */
        { USB_DEVICE(VENDOR_FINTEK, 0x0602) },
        /* Fintek eHome Infrared Transceiver (in the AOpen MP45) */
@@ -292,9 +304,12 @@ static struct usb_device_id mceusb_dev_table[] = {
        { USB_DEVICE(VENDOR_NORTHSTAR, 0xe004) },
        /* TiVo PC IR Receiver */
        { USB_DEVICE(VENDOR_TIVO, 0x2000) },
-       /* Conexant SDK */
+       /* Conexant Hybrid TV "Shelby" Polaris SDK */
        { USB_DEVICE(VENDOR_CONEXANT, 0x58a1),
          .driver_info = POLARIS_EVK },
+       /* Conexant Hybrid TV RDU253S Polaris */
+       { USB_DEVICE(VENDOR_CONEXANT, 0x58a5),
+         .driver_info = CX_HYBRID_TV },
        /* Terminating entry */
        { }
 };
@@ -303,7 +318,10 @@ static struct usb_device_id mceusb_dev_table[] = {
 struct mceusb_dev {
        /* ir-core bits */
        struct ir_dev_props *props;
-       struct ir_raw_event rawir;
+
+       /* optional features we can enable */
+       bool carrier_report_enabled;
+       bool learning_enabled;
 
        /* core device bits */
        struct device *dev;
@@ -318,6 +336,8 @@ struct mceusb_dev {
        /* buffers and dma */
        unsigned char *buf_in;
        unsigned int len_in;
+       dma_addr_t dma_in;
+       dma_addr_t dma_out;
 
        enum {
                CMD_HEADER = 0,
@@ -325,15 +345,14 @@ struct mceusb_dev {
                CMD_DATA,
                PARSE_IRDATA,
        } parser_state;
-       u8 cmd, rem;            /* Remaining IR data bytes in packet */
 
-       dma_addr_t dma_in;
-       dma_addr_t dma_out;
+       u8 cmd, rem;            /* Remaining IR data bytes in packet */
 
        struct {
                u32 connected:1;
-               u32 tx_mask_inverted:1;
+               u32 tx_mask_normal:1;
                u32 microsoft_gen1:1;
+               u32 no_tx:1;
        } flags;
 
        /* transmit support */
@@ -408,9 +427,10 @@ static int mceusb_cmdsize(u8 cmd, u8 subcmd)
                case MCE_CMD_UNKNOWN:
                case MCE_CMD_S_CARRIER:
                case MCE_CMD_S_TIMEOUT:
-               case MCE_CMD_G_RXSENSOR:
+               case MCE_RSP_PULSE_COUNT:
                        datasize = 2;
                        break;
+               case MCE_CMD_SIG_END:
                case MCE_CMD_S_TXMASK:
                case MCE_CMD_S_RXSENSOR:
                        datasize = 1;
@@ -433,7 +453,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
                return;
 
        /* skip meaningless 0xb1 0x60 header bytes on orig receiver */
-       if (ir->flags.microsoft_gen1 && !out)
+       if (ir->flags.microsoft_gen1 && !out && !offset)
                skip = 2;
 
        if (len <= skip)
@@ -491,6 +511,9 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
                break;
        case MCE_COMMAND_HEADER:
                switch (subcmd) {
+               case MCE_CMD_SIG_END:
+                       dev_info(dev, "End of signal\n");
+                       break;
                case MCE_CMD_PING:
                        dev_info(dev, "Ping\n");
                        break;
@@ -525,10 +548,11 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
                                 inout, data1 == 0x02 ? "short" : "long");
                        break;
                case MCE_CMD_G_RXSENSOR:
-                       if (len == 2)
+               /* aka MCE_RSP_PULSE_COUNT */
+                       if (out)
                                dev_info(dev, "Get receive sensor\n");
-                       else
-                               dev_info(dev, "Received pulse count is %d\n",
+                       else if (ir->learning_enabled)
+                               dev_info(dev, "RX pulse count: %d\n",
                                         ((data1 << 8) | data2));
                        break;
                case MCE_RSP_CMD_INVALID:
@@ -724,16 +748,16 @@ out:
        return ret ? ret : n;
 }
 
-/* Sets active IR outputs -- mce devices typically (all?) have two */
+/* Sets active IR outputs -- mce devices typically have two */
 static int mceusb_set_tx_mask(void *priv, u32 mask)
 {
        struct mceusb_dev *ir = priv;
 
-       if (ir->flags.tx_mask_inverted)
+       if (ir->flags.tx_mask_normal)
+               ir->tx_mask = mask;
+       else
                ir->tx_mask = (mask != MCE_DEFAULT_TX_MASK ?
                                mask ^ MCE_DEFAULT_TX_MASK : mask) << 1;
-       else
-               ir->tx_mask = mask;
 
        return 0;
 }
@@ -752,7 +776,7 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
 
                if (carrier == 0) {
                        ir->carrier = carrier;
-                       cmdbuf[2] = 0x01;
+                       cmdbuf[2] = MCE_CMD_SIG_END;
                        cmdbuf[3] = MCE_IRDATA_TRAILER;
                        dev_dbg(ir->dev, "%s: disabling carrier "
                                "modulation\n", __func__);
@@ -782,6 +806,34 @@ static int mceusb_set_tx_carrier(void *priv, u32 carrier)
        return carrier;
 }
 
+/*
+ * We don't do anything but print debug spew for many of the command bits
+ * we receive from the hardware, but some of them are useful information
+ * we want to store so that we can use them.
+ */
+static void mceusb_handle_command(struct mceusb_dev *ir, int index)
+{
+       u8 hi = ir->buf_in[index + 1] & 0xff;
+       u8 lo = ir->buf_in[index + 2] & 0xff;
+
+       switch (ir->buf_in[index]) {
+       /* 2-byte return value commands */
+       case MCE_CMD_S_TIMEOUT:
+               ir->props->timeout = MS_TO_NS((hi << 8 | lo) / 2);
+               break;
+
+       /* 1-byte return value commands */
+       case MCE_CMD_S_TXMASK:
+               ir->tx_mask = hi;
+               break;
+       case MCE_CMD_S_RXSENSOR:
+               ir->learning_enabled = (hi == 0x02);
+               break;
+       default:
+               break;
+       }
+}
+
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 {
        DEFINE_IR_RAW_EVENT(rawir);
@@ -791,39 +843,30 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
        if (ir->flags.microsoft_gen1)
                i = 2;
 
+       /* if there's no data, just return now */
+       if (buf_len <= i)
+               return;
+
        for (; i < buf_len; i++) {
                switch (ir->parser_state) {
                case SUBCMD:
                        ir->rem = mceusb_cmdsize(ir->cmd, ir->buf_in[i]);
                        mceusb_dev_printdata(ir, ir->buf_in, i - 1,
                                             ir->rem + 2, false);
+                       mceusb_handle_command(ir, i);
                        ir->parser_state = CMD_DATA;
                        break;
                case PARSE_IRDATA:
                        ir->rem--;
                        rawir.pulse = ((ir->buf_in[i] & MCE_PULSE_BIT) != 0);
                        rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
-                                        * MCE_TIME_UNIT * 1000;
-
-                       if ((ir->buf_in[i] & MCE_PULSE_MASK) == 0x7f) {
-                               if (ir->rawir.pulse == rawir.pulse) {
-                                       ir->rawir.duration += rawir.duration;
-                               } else {
-                                       ir->rawir.duration = rawir.duration;
-                                       ir->rawir.pulse = rawir.pulse;
-                               }
-                               if (ir->rem)
-                                       break;
-                       }
-                       rawir.duration += ir->rawir.duration;
-                       ir->rawir.duration = 0;
-                       ir->rawir.pulse = rawir.pulse;
+                                        * MS_TO_NS(MCE_TIME_UNIT);
 
                        dev_dbg(ir->dev, "Storing %s with duration %d\n",
                                rawir.pulse ? "pulse" : "space",
                                rawir.duration);
 
-                       ir_raw_event_store(ir->idev, &rawir);
+                       ir_raw_event_store_with_filter(ir->idev, &rawir);
                        break;
                case CMD_DATA:
                        ir->rem--;
@@ -839,17 +882,10 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
                                continue;
                        }
                        ir->rem = (ir->cmd & MCE_PACKET_LENGTH_MASK);
-                       mceusb_dev_printdata(ir, ir->buf_in, i, ir->rem + 1, false);
-                       if (ir->rem) {
+                       mceusb_dev_printdata(ir, ir->buf_in,
+                                            i, ir->rem + 1, false);
+                       if (ir->rem)
                                ir->parser_state = PARSE_IRDATA;
-                               break;
-                       }
-                       /*
-                        * a package with len=0 (e. g. 0x80) means end of
-                        * data. We could use it to do the call to
-                        * ir_raw_event_handle(). For now, we don't need to
-                        * use it.
-                        */
                        break;
                }
 
@@ -984,9 +1020,11 @@ static void mceusb_get_parameters(struct mceusb_dev *ir)
        mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
        mce_sync_in(ir, NULL, maxp);
 
-       /* get the transmitter bitmask */
-       mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
-       mce_sync_in(ir, NULL, maxp);
+       if (!ir->flags.no_tx) {
+               /* get the transmitter bitmask */
+               mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
+               mce_sync_in(ir, NULL, maxp);
+       }
 
        /* get receiver timeout value */
        mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
@@ -1035,12 +1073,18 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
        props->priv = ir;
        props->driver_type = RC_DRIVER_IR_RAW;
        props->allowed_protos = IR_TYPE_ALL;
-       props->s_tx_mask = mceusb_set_tx_mask;
-       props->s_tx_carrier = mceusb_set_tx_carrier;
-       props->tx_ir = mceusb_tx_ir;
+       props->timeout = MS_TO_NS(1000);
+       if (!ir->flags.no_tx) {
+               props->s_tx_mask = mceusb_set_tx_mask;
+               props->s_tx_carrier = mceusb_set_tx_carrier;
+               props->tx_ir = mceusb_tx_ir;
+       }
 
        ir->props = props;
 
+       usb_to_input_id(ir->usbdev, &idev->id);
+       idev->dev.parent = ir->dev;
+
        if (mceusb_model[ir->model].rc_map)
                rc_map = mceusb_model[ir->model].rc_map;
 
@@ -1074,16 +1118,16 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
        enum mceusb_model_type model = id->driver_info;
        bool is_gen3;
        bool is_microsoft_gen1;
-       bool tx_mask_inverted;
+       bool tx_mask_normal;
        bool is_polaris;
 
-       dev_dbg(&intf->dev, "%s called\n", __func__);
+       dev_dbg(&intf->dev, "%s called\n", __func__);
 
        idesc  = intf->cur_altsetting;
 
        is_gen3 = mceusb_model[model].mce_gen3;
        is_microsoft_gen1 = mceusb_model[model].mce_gen1;
-       tx_mask_inverted = mceusb_model[model].tx_mask_inverted;
+       tx_mask_normal = mceusb_model[model].tx_mask_normal;
        is_polaris = mceusb_model[model].is_polaris;
 
        if (is_polaris) {
@@ -1107,7 +1151,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
                        ep_in = ep;
                        ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
                        ep_in->bInterval = 1;
-                       dev_dbg(&intf->dev, "acceptable inbound endpoint "
+                       dev_dbg(&intf->dev, "acceptable inbound endpoint "
                                "found\n");
                }
 
@@ -1122,12 +1166,12 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
                        ep_out = ep;
                        ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
                        ep_out->bInterval = 1;
-                       dev_dbg(&intf->dev, "acceptable outbound endpoint "
+                       dev_dbg(&intf->dev, "acceptable outbound endpoint "
                                "found\n");
                }
        }
        if (ep_in == NULL) {
-               dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");
+               dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");
                return -ENODEV;
        }
 
@@ -1150,11 +1194,10 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
        ir->dev = &intf->dev;
        ir->len_in = maxp;
        ir->flags.microsoft_gen1 = is_microsoft_gen1;
-       ir->flags.tx_mask_inverted = tx_mask_inverted;
+       ir->flags.tx_mask_normal = tx_mask_normal;
+       ir->flags.no_tx = mceusb_model[model].no_tx;
        ir->model = model;
 
-       init_ir_raw_event(&ir->rawir);
-
        /* Saving usb interface data for use by the transmitter routine */
        ir->usb_ep_in = ep_in;
        ir->usb_ep_out = ep_out;
@@ -1191,7 +1234,8 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
 
        mceusb_get_parameters(ir);
 
-       mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK);
+       if (!ir->flags.no_tx)
+               mceusb_set_tx_mask(ir, MCE_DEFAULT_TX_MASK);
 
        usb_set_intfdata(intf, ir);
 
index 301be53aee857298c43855df887a90ece26a2d8c..acc729c79ceca10afb96b08b101095c1a3e1dc03 100644 (file)
@@ -603,6 +603,8 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
        count = nvt->pkts;
        nvt_dbg_verbose("Processing buffer of len %d", count);
 
+       init_ir_raw_event(&rawir);
+
        for (i = 0; i < count; i++) {
                nvt->pkts--;
                sample = nvt->buf[i];
@@ -643,11 +645,15 @@ static void nvt_process_rx_ir_data(struct nvt_dev *nvt)
                 * indicates end of IR signal, but new data incoming. In both
                 * cases, it means we're ready to call ir_raw_event_handle
                 */
-               if (sample == BUF_PULSE_BIT || ((sample != BUF_LEN_MASK) &&
-                   (sample & BUF_REPEAT_MASK) == BUF_REPEAT_BYTE))
+               if ((sample == BUF_PULSE_BIT) && nvt->pkts) {
+                       nvt_dbg("Calling ir_raw_event_handle (signal end)\n");
                        ir_raw_event_handle(nvt->rdev);
+               }
        }
 
+       nvt_dbg("Calling ir_raw_event_handle (buffer empty)\n");
+       ir_raw_event_handle(nvt->rdev);
+
        if (nvt->pkts) {
                nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts);
                nvt->pkts = 0;
index 548381c35bfd1573bf5886b648100e0d06a63f11..3a20aef67d08f97f7f0b92b143a85a67bbe24304 100644 (file)
@@ -34,8 +34,9 @@
 #include <linux/device.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/input.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
 #include <media/ir-core.h>
 
 #define DRIVER_VERSION "1.61"
@@ -140,7 +141,9 @@ static struct usb_driver streamzap_driver = {
 
 static void sz_push(struct streamzap_ir *sz, struct ir_raw_event rawir)
 {
-       ir_raw_event_store(sz->idev, &rawir);
+       dev_dbg(sz->dev, "Storing %s with duration %u us\n",
+               (rawir.pulse ? "pulse" : "space"), rawir.duration);
+       ir_raw_event_store_with_filter(sz->idev, &rawir);
 }
 
 static void sz_push_full_pulse(struct streamzap_ir *sz,
@@ -167,7 +170,6 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,
                        rawir.duration *= 1000;
                        rawir.duration &= IR_MAX_DURATION;
                }
-               dev_dbg(sz->dev, "ls %u\n", rawir.duration);
                sz_push(sz, rawir);
 
                sz->idle = false;
@@ -180,7 +182,6 @@ static void sz_push_full_pulse(struct streamzap_ir *sz,
        sz->sum += rawir.duration;
        rawir.duration *= 1000;
        rawir.duration &= IR_MAX_DURATION;
-       dev_dbg(sz->dev, "p %u\n", rawir.duration);
        sz_push(sz, rawir);
 }
 
@@ -200,7 +201,6 @@ static void sz_push_full_space(struct streamzap_ir *sz,
        rawir.duration += SZ_RESOLUTION / 2;
        sz->sum += rawir.duration;
        rawir.duration *= 1000;
-       dev_dbg(sz->dev, "s %u\n", rawir.duration);
        sz_push(sz, rawir);
 }
 
@@ -221,8 +221,6 @@ static void streamzap_callback(struct urb *urb)
        struct streamzap_ir *sz;
        unsigned int i;
        int len;
-       static int timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
-                               IR_MAX_DURATION) | 0x03000000);
 
        if (!urb)
                return;
@@ -246,7 +244,7 @@ static void streamzap_callback(struct urb *urb)
 
        dev_dbg(sz->dev, "%s: received urb, len %d\n", __func__, len);
        for (i = 0; i < len; i++) {
-               dev_dbg(sz->dev, "sz idx %d: %x\n",
+               dev_dbg(sz->dev, "sz->buf_in[%d]: %x\n",
                        i, (unsigned char)sz->buf_in[i]);
                switch (sz->decoder_state) {
                case PulseSpace:
@@ -273,7 +271,7 @@ static void streamzap_callback(struct urb *urb)
                                DEFINE_IR_RAW_EVENT(rawir);
 
                                rawir.pulse = false;
-                               rawir.duration = timeout;
+                               rawir.duration = sz->props->timeout;
                                sz->idle = true;
                                if (sz->timeout_enabled)
                                        sz_push(sz, rawir);
@@ -335,6 +333,9 @@ static struct input_dev *streamzap_init_input_dev(struct streamzap_ir *sz)
 
        sz->props = props;
 
+       usb_to_input_id(sz->usbdev, &idev->id);
+       idev->dev.parent = sz->dev;
+
        ret = ir_input_register(idev, RC_MAP_STREAMZAP, props, DRIVER_NAME);
        if (ret < 0) {
                dev_err(dev, "remote input device register failed\n");
@@ -444,6 +445,8 @@ static int __devinit streamzap_probe(struct usb_interface *intf,
        sz->decoder_state = PulseSpace;
        /* FIXME: don't yet have a way to set this */
        sz->timeout_enabled = true;
+       sz->props->timeout = (((SZ_TIMEOUT * SZ_RESOLUTION * 1000) &
+                               IR_MAX_DURATION) | 0x03000000);
        #if 0
        /* not yet supported, depends on patches from maxim */
        /* see also: LIRC_GET_REC_RESOLUTION and LIRC_SET_REC_TIMEOUT */
index 05bde9ccb770b377eb327409a707ef38b5e25a17..1d1d8d200755a2c9af0ca241b983dd55f1a672a4 100644 (file)
@@ -558,7 +558,7 @@ static void saa7146_set_window(struct saa7146_dev *dev, int width, int height, e
 static void saa7146_set_position(struct saa7146_dev *dev, int w_x, int w_y, int w_height, enum v4l2_field field, u32 pixelformat)
 {
        struct saa7146_vv *vv = dev->vv_data;
-       struct saa7146_format *sfmt = format_by_fourcc(dev, pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pixelformat);
 
        int b_depth = vv->ov_fmt->depth;
        int b_bpl = vv->ov_fb.fmt.bytesperline;
@@ -702,7 +702,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
        struct saa7146_vv *vv = dev->vv_data;
        struct saa7146_video_dma vdma1;
 
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        int width = buf->fmt->width;
        int height = buf->fmt->height;
@@ -827,7 +827,7 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
        struct saa7146_video_dma vdma2;
        struct saa7146_video_dma vdma3;
 
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        int width = buf->fmt->width;
        int height = buf->fmt->height;
@@ -994,7 +994,7 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
 
 void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struct saa7146_buf *next)
 {
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
        struct saa7146_vv *vv = dev->vv_data;
        u32 vdma1_prot_addr;
 
index 741c5732b430613ff816da949ba3116a4f23c1c9..d246910129e80c74065eeae233da090396614f45 100644 (file)
@@ -84,7 +84,7 @@ static struct saa7146_format formats[] = {
 
 static int NUM_FORMATS = sizeof(formats)/sizeof(struct saa7146_format);
 
-struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc)
+struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
 {
        int i, j = NUM_FORMATS;
 
@@ -266,7 +266,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
        struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
        struct scatterlist *list = dma->sglist;
        int length = dma->sglen;
-       struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+       struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
        DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
 
@@ -408,7 +408,7 @@ static int video_begin(struct saa7146_fh *fh)
                }
        }
 
-       fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        /* we need to have a valid format set here */
        BUG_ON(NULL == fmt);
 
@@ -460,7 +460,7 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
                return -EBUSY;
        }
 
-       fmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        /* we need to have a valid format set here */
        BUG_ON(NULL == fmt);
 
@@ -536,7 +536,7 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
                return -EPERM;
 
        /* check args */
-       fmt = format_by_fourcc(dev, fb->fmt.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
@@ -760,7 +760,7 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_forma
 
        DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
 
-       fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat);
+       fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
@@ -1264,7 +1264,7 @@ static int buffer_prepare(struct videobuf_queue *q,
                buf->fmt       = &fh->video_fmt;
                buf->vb.field  = fh->video_fmt.field;
 
-               sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
+               sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
 
                release_all_pagetables(dev, buf);
                if( 0 != IS_PLANAR(sfmt->trans)) {
@@ -1378,7 +1378,7 @@ static int video_open(struct saa7146_dev *dev, struct file *file)
        fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
        fh->video_fmt.bytesperline = 0;
        fh->video_fmt.field = V4L2_FIELD_ANY;
-       sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
+       sfmt = saa7146_format_by_fourcc(dev,fh->video_fmt.pixelformat);
        fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
 
        videobuf_queue_sg_init(&fh->video_q, &video_qops,
index 5bf4985daede6a49e9b35adcb3b3256b51a14924..05e832f61c3e88772e1ae8b3b1059a0825a5b86c 100644 (file)
@@ -361,7 +361,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations rtrack_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops rtrack_ioctl_ops = {
@@ -412,13 +412,6 @@ static int __init rtrack_init(void)
        rt->vdev.release = video_device_release_empty;
        video_set_drvdata(&rt->vdev, rt);
 
-       if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(&rt->v4l2_dev);
-               release_region(rt->io, 2);
-               return -EINVAL;
-       }
-       v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
-
        /* Set up the I/O locking */
 
        mutex_init(&rt->lock);
@@ -430,6 +423,13 @@ static int __init rtrack_init(void)
        sleep_delay(2000000);   /* make sure it's totally down  */
        outb(0xc0, rt->io);             /* steady volume, mute card     */
 
+       if (video_register_device(&rt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(&rt->v4l2_dev);
+               release_region(rt->io, 2);
+               return -EINVAL;
+       }
+       v4l2_info(v4l2_dev, "AIMSlab RadioTrack/RadioReveal card driver.\n");
+
        return 0;
 }
 
index c22311393624d26ebfbe0d4db8776a7c536b3a70..dd8a6ab0d437ab10022d1b65f1d802cc8d2b006c 100644 (file)
@@ -324,7 +324,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static const struct v4l2_file_operations aztech_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops aztech_ioctl_ops = {
@@ -375,6 +375,8 @@ static int __init aztech_init(void)
        az->vdev.ioctl_ops = &aztech_ioctl_ops;
        az->vdev.release = video_device_release_empty;
        video_set_drvdata(&az->vdev, az);
+       /* mute card - prevents noisy bootups */
+       outb(0, az->io);
 
        if (video_register_device(&az->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
@@ -383,8 +385,6 @@ static int __init aztech_init(void)
        }
 
        v4l2_info(v4l2_dev, "Aztech radio card driver v1.00/19990224 rkroll@exploits.org\n");
-       /* mute card - prevents noisy bootups */
-       outb(0, az->io);
        return 0;
 }
 
index b701ea6e7c7379fc0593fae6c22c4678152cd4e7..bc9ad0897c559b9142aea9ba7cbf486caaf1d5c4 100644 (file)
@@ -328,11 +328,10 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
        unsigned char readbuf[RDS_BUFFER];
        int i = 0;
 
+       mutex_lock(&dev->lock);
        if (dev->rdsstat == 0) {
-               mutex_lock(&dev->lock);
                dev->rdsstat = 1;
                outb(0x80, dev->io);        /* Select RDS fifo */
-               mutex_unlock(&dev->lock);
                init_timer(&dev->readtimer);
                dev->readtimer.function = cadet_handler;
                dev->readtimer.data = (unsigned long)dev;
@@ -340,12 +339,15 @@ static ssize_t cadet_read(struct file *file, char __user *data, size_t count, lo
                add_timer(&dev->readtimer);
        }
        if (dev->rdsin == dev->rdsout) {
+               mutex_unlock(&dev->lock);
                if (file->f_flags & O_NONBLOCK)
                        return -EWOULDBLOCK;
                interruptible_sleep_on(&dev->read_queue);
+               mutex_lock(&dev->lock);
        }
        while (i < count && dev->rdsin != dev->rdsout)
                readbuf[i++] = dev->rdsbuf[dev->rdsout++];
+       mutex_unlock(&dev->lock);
 
        if (copy_to_user(data, readbuf, i))
                return -EFAULT;
@@ -525,9 +527,11 @@ static int cadet_open(struct file *file)
 {
        struct cadet *dev = video_drvdata(file);
 
+       mutex_lock(&dev->lock);
        dev->users++;
        if (1 == dev->users)
                init_waitqueue_head(&dev->read_queue);
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -535,11 +539,13 @@ static int cadet_release(struct file *file)
 {
        struct cadet *dev = video_drvdata(file);
 
+       mutex_lock(&dev->lock);
        dev->users--;
        if (0 == dev->users) {
                del_timer_sync(&dev->readtimer);
                dev->rdsstat = 0;
        }
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -559,7 +565,7 @@ static const struct v4l2_file_operations cadet_fops = {
        .open           = cadet_open,
        .release        = cadet_release,
        .read           = cadet_read,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll           = cadet_poll,
 };
 
index 79039674a0e0bddff9976de584437a60b948e789..28fa85ba2087cfd56c067ac51a9669945eb44757 100644 (file)
@@ -361,7 +361,7 @@ MODULE_DEVICE_TABLE(pci, gemtek_pci_id);
 
 static const struct v4l2_file_operations gemtek_pci_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops gemtek_pci_ioctl_ops = {
@@ -422,11 +422,11 @@ static int __devinit gemtek_pci_probe(struct pci_dev *pdev, const struct pci_dev
        card->vdev.release = video_device_release_empty;
        video_set_drvdata(&card->vdev, card);
 
+       gemtek_pci_mute(card);
+
        if (video_register_device(&card->vdev, VFL_TYPE_RADIO, nr_radio) < 0)
                goto err_video;
 
-       gemtek_pci_mute(card);
-
        v4l2_info(v4l2_dev, "Gemtek PCI Radio (rev. %d) found at 0x%04x-0x%04x.\n",
                pdev->revision, card->iobase, card->iobase + card->length - 1);
 
index 73985f641f072d361d128f769530281b150ffbfb..259936422e493b4dcf6dd6742d17bc5acd5b2995 100644 (file)
@@ -378,7 +378,7 @@ static int gemtek_probe(struct gemtek *gt)
 
 static const struct v4l2_file_operations gemtek_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -577,12 +577,6 @@ static int __init gemtek_init(void)
        gt->vdev.release = video_device_release_empty;
        video_set_drvdata(&gt->vdev, gt);
 
-       if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(gt->io, 1);
-               return -EBUSY;
-       }
-
        /* Set defaults */
        gt->lastfreq = GEMTEK_LOWFREQ;
        gt->bu2614data = 0;
@@ -590,6 +584,12 @@ static int __init gemtek_init(void)
        if (initmute)
                gemtek_mute(gt);
 
+       if (video_register_device(&gt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(gt->io, 1);
+               return -EBUSY;
+       }
+
        return 0;
 }
 
index 08f1051979cae6f7508026dc0e957a23de775795..6af61bfeb1780089718f96884f6dc0dfc8550943 100644 (file)
@@ -299,7 +299,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations maestro_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops maestro_ioctl_ops = {
@@ -383,22 +383,20 @@ static int __devinit maestro_probe(struct pci_dev *pdev,
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
 
+       if (!radio_power_on(dev)) {
+               retval = -EIO;
+               goto errfr1;
+       }
+
        retval = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
        if (retval) {
                v4l2_err(v4l2_dev, "can't register video device!\n");
                goto errfr1;
        }
 
-       if (!radio_power_on(dev)) {
-               retval = -EIO;
-               goto errunr;
-       }
-
        v4l2_info(v4l2_dev, "version " DRIVER_VERSION "\n");
 
        return 0;
-errunr:
-       video_unregister_device(&dev->vdev);
 errfr1:
        v4l2_device_unregister(v4l2_dev);
 errfr:
index 255d40df4b461e9e5287462c08901a78758a565f..6459a220b0dd46ddb22326e0595f8964ae4915d2 100644 (file)
@@ -346,7 +346,7 @@ static int vidioc_s_ctrl(struct file *file, void *priv,
 
 static const struct v4l2_file_operations maxiradio_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops maxiradio_ioctl_ops = {
index 4ff885445fd455371823ad55a00f82e4c2afdcfe..3fb76e3834c99da96e8621ab4ecd89458913d259 100644 (file)
@@ -33,6 +33,7 @@ struct pcm20 {
        unsigned long freq;
        int muted;
        struct snd_miro_aci *aci;
+       struct mutex lock;
 };
 
 static struct pcm20 pcm20_card = {
@@ -72,7 +73,7 @@ static int pcm20_setfreq(struct pcm20 *dev, unsigned long freq)
 
 static const struct v4l2_file_operations pcm20_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int vidioc_querycap(struct file *file, void *priv,
@@ -229,7 +230,7 @@ static int __init pcm20_init(void)
                return -ENODEV;
        }
        strlcpy(v4l2_dev->name, "miropcm20", sizeof(v4l2_dev->name));
-
+       mutex_init(&dev->lock);
 
        res = v4l2_device_register(NULL, v4l2_dev);
        if (res < 0) {
@@ -242,6 +243,7 @@ static int __init pcm20_init(void)
        dev->vdev.fops = &pcm20_fops;
        dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
        dev->vdev.release = video_device_release_empty;
+       dev->vdev.lock = &dev->lock;
        video_set_drvdata(&dev->vdev, dev);
 
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0)
index a79296aac9a9636e408a27a7da9a42cf9c4e21e3..8d6ea591bd188815c374ddf5c5e603a5aa3d6e8e 100644 (file)
@@ -266,7 +266,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations rtrack2_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops rtrack2_ioctl_ops = {
@@ -315,6 +315,10 @@ static int __init rtrack2_init(void)
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
 
+       /* mute card - prevents noisy bootups */
+       outb(1, dev->io);
+       dev->muted = 1;
+
        mutex_init(&dev->lock);
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
@@ -324,10 +328,6 @@ static int __init rtrack2_init(void)
 
        v4l2_info(v4l2_dev, "AIMSlab Radiotrack II card driver.\n");
 
-       /* mute card - prevents noisy bootups */
-       outb(1, dev->io);
-       dev->muted = 1;
-
        return 0;
 }
 
index 985359d18aa58fd8e350d0e06b05b66020534bc5..b5a5f89e238a91fe432326d0da9487cf32ad9943 100644 (file)
@@ -260,7 +260,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations fmi_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops fmi_ioctl_ops = {
@@ -382,6 +382,9 @@ static int __init fmi_init(void)
 
        mutex_init(&fmi->lock);
 
+       /* mute card - prevents noisy bootups */
+       fmi_mute(fmi);
+
        if (video_register_device(&fmi->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
                release_region(fmi->io, 2);
@@ -391,8 +394,6 @@ static int __init fmi_init(void)
        }
 
        v4l2_info(v4l2_dev, "card driver at 0x%x\n", fmi->io);
-       /* mute card - prevents noisy bootups */
-       fmi_mute(fmi);
        return 0;
 }
 
index 52c7bbb32b8b7ea10312ff58716c47f1ed472bd2..dc3f04c52d5e11e923829e74a548d78d1b3e6cad 100644 (file)
@@ -376,7 +376,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations fmr2_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops fmr2_ioctl_ops = {
@@ -424,6 +424,10 @@ static int __init fmr2_init(void)
        fmr2->vdev.release = video_device_release_empty;
        video_set_drvdata(&fmr2->vdev, fmr2);
 
+       /* mute card - prevents noisy bootups */
+       fmr2_mute(fmr2->io);
+       fmr2_product_info(fmr2);
+
        if (video_register_device(&fmr2->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(v4l2_dev);
                release_region(fmr2->io, 2);
@@ -431,11 +435,6 @@ static int __init fmr2_init(void)
        }
 
        v4l2_info(v4l2_dev, "SF16FMR2 radio card driver at 0x%x.\n", fmr2->io);
-       /* mute card - prevents noisy bootups */
-       mutex_lock(&fmr2->lock);
-       fmr2_mute(fmr2->io);
-       fmr2_product_info(fmr2);
-       mutex_unlock(&fmr2->lock);
        debug_print((KERN_DEBUG "card_type %d\n", fmr2->card_type));
        return 0;
 }
index 03829e6818bd4bc156d922c7c19ee8daaabc0fc8..726d367ad8d0f2119b5e832d8ccca593d2a6d3fa 100644 (file)
@@ -53,7 +53,8 @@ struct radio_si4713_device {
 /* radio_si4713_fops - file operations interface */
 static const struct v4l2_file_operations radio_si4713_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       /* Note: locking is done at the subdev level in the i2c driver. */
+       .unlocked_ioctl = video_ioctl2,
 };
 
 /* Video4Linux Interface */
index 789d2ec66e1948d2d071c3424f92dc820b0bcc0b..0e71d816c725885535cc4d1da4f992809d0d6257 100644 (file)
@@ -142,7 +142,6 @@ struct tea5764_device {
        struct video_device             *videodev;
        struct tea5764_regs             regs;
        struct mutex                    mutex;
-       int                             users;
 };
 
 /* I2C code related */
@@ -458,41 +457,10 @@ static int vidioc_s_audio(struct file *file, void *priv,
        return 0;
 }
 
-static int tea5764_open(struct file *file)
-{
-       /* Currently we support only one device */
-       struct tea5764_device *radio = video_drvdata(file);
-
-       mutex_lock(&radio->mutex);
-       /* Only exclusive access */
-       if (radio->users) {
-               mutex_unlock(&radio->mutex);
-               return -EBUSY;
-       }
-       radio->users++;
-       mutex_unlock(&radio->mutex);
-       file->private_data = radio;
-       return 0;
-}
-
-static int tea5764_close(struct file *file)
-{
-       struct tea5764_device *radio = video_drvdata(file);
-
-       if (!radio)
-               return -ENODEV;
-       mutex_lock(&radio->mutex);
-       radio->users--;
-       mutex_unlock(&radio->mutex);
-       return 0;
-}
-
 /* File system interface */
 static const struct v4l2_file_operations tea5764_fops = {
        .owner          = THIS_MODULE,
-       .open           = tea5764_open,
-       .release        = tea5764_close,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops tea5764_ioctl_ops = {
@@ -527,7 +495,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
        int ret;
 
        PDEBUG("probe");
-       radio = kmalloc(sizeof(struct tea5764_device), GFP_KERNEL);
+       radio = kzalloc(sizeof(struct tea5764_device), GFP_KERNEL);
        if (!radio)
                return -ENOMEM;
 
@@ -555,12 +523,7 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, radio);
        video_set_drvdata(radio->videodev, radio);
-
-       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
-       if (ret < 0) {
-               PWARN("Could not register video device!");
-               goto errrel;
-       }
+       radio->videodev->lock = &radio->mutex;
 
        /* initialize and power off the chip */
        tea5764_i2c_read(radio);
@@ -568,6 +531,12 @@ static int __devinit tea5764_i2c_probe(struct i2c_client *client,
        tea5764_mute(radio, 1);
        tea5764_power_down(radio);
 
+       ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
+       if (ret < 0) {
+               PWARN("Could not register video device!");
+               goto errrel;
+       }
+
        PINFO("registered.");
        return 0;
 errrel:
index fc1c860fd43844c188d4e42cc845a5f40b4ae957..a32663917059c1cd4734247452c33444c02ad5d2 100644 (file)
@@ -338,7 +338,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations terratec_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops terratec_ioctl_ops = {
@@ -389,6 +389,9 @@ static int __init terratec_init(void)
 
        mutex_init(&tt->lock);
 
+       /* mute card - prevents noisy bootups */
+       tt_write_vol(tt, 0);
+
        if (video_register_device(&tt->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(&tt->v4l2_dev);
                release_region(tt->io, 2);
@@ -396,9 +399,6 @@ static int __init terratec_init(void)
        }
 
        v4l2_info(v4l2_dev, "TERRATEC ActivRadio Standalone card driver.\n");
-
-       /* mute card - prevents noisy bootups */
-       tt_write_vol(tt, 0);
        return 0;
 }
 
index b8bb3ef47df5c72153e7e1964ddbc679b3c1b8ed..a185610b376be1a14e79b52751c7f95aab777dd0 100644 (file)
@@ -34,6 +34,7 @@ struct timbradio {
        struct v4l2_subdev      *sd_dsp;
        struct video_device     video_dev;
        struct v4l2_device      v4l2_dev;
+       struct mutex            lock;
 };
 
 
@@ -142,7 +143,7 @@ static const struct v4l2_ioctl_ops timbradio_ioctl_ops = {
 
 static const struct v4l2_file_operations timbradio_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static int __devinit timbradio_probe(struct platform_device *pdev)
@@ -164,6 +165,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        }
 
        tr->pdata = *pdata;
+       mutex_init(&tr->lock);
 
        strlcpy(tr->video_dev.name, "Timberdale Radio",
                sizeof(tr->video_dev.name));
@@ -171,6 +173,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        tr->video_dev.ioctl_ops = &timbradio_ioctl_ops;
        tr->video_dev.release = video_device_release_empty;
        tr->video_dev.minor = -1;
+       tr->video_dev.lock = &tr->lock;
 
        strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
        err = v4l2_device_register(NULL, &tr->v4l2_dev);
index 9d6dcf8af5b01de328436a0955ae190fe651aa72..22fa9cc28abed060cff57e1e3a78227575c9ee36 100644 (file)
@@ -344,7 +344,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 
 static const struct v4l2_file_operations trust_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops trust_ioctl_ops = {
@@ -396,14 +396,6 @@ static int __init trust_init(void)
        tr->vdev.release = video_device_release_empty;
        video_set_drvdata(&tr->vdev, tr);
 
-       if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(tr->io, 2);
-               return -EINVAL;
-       }
-
-       v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
-
        write_i2c(tr, 2, TDA7318_ADDR, 0x80);   /* speaker att. LF = 0 dB */
        write_i2c(tr, 2, TDA7318_ADDR, 0xa0);   /* speaker att. RF = 0 dB */
        write_i2c(tr, 2, TDA7318_ADDR, 0xc0);   /* speaker att. LR = 0 dB */
@@ -418,6 +410,14 @@ static int __init trust_init(void)
        /* mute card - prevents noisy bootups */
        tr_setmute(tr, 1);
 
+       if (video_register_device(&tr->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(tr->io, 2);
+               return -EINVAL;
+       }
+
+       v4l2_info(v4l2_dev, "Trust FM Radio card driver v1.0.\n");
+
        return 0;
 }
 
index b1f630527dc12df962d9eeef051413e800e6a785..8dbbf08f22077ad2b7c84e8e3992d3b33eab88e7 100644 (file)
@@ -317,7 +317,7 @@ static int vidioc_log_status(struct file *file, void *priv)
 
 static const struct v4l2_file_operations typhoon_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops typhoon_ioctl_ops = {
@@ -344,18 +344,18 @@ static int __init typhoon_init(void)
 
        strlcpy(v4l2_dev->name, "typhoon", sizeof(v4l2_dev->name));
        dev->io = io;
-       dev->curfreq = dev->mutefreq = mutefreq;
 
        if (dev->io == -1) {
                v4l2_err(v4l2_dev, "You must set an I/O address with io=0x316 or io=0x336\n");
                return -EINVAL;
        }
 
-       if (dev->mutefreq < 87000 || dev->mutefreq > 108500) {
+       if (mutefreq < 87000 || mutefreq > 108500) {
                v4l2_err(v4l2_dev, "You must set a frequency (in kHz) used when muting the card,\n");
                v4l2_err(v4l2_dev, "e.g. with \"mutefreq=87500\" (87000 <= mutefreq <= 108500)\n");
                return -EINVAL;
        }
+       dev->curfreq = dev->mutefreq = mutefreq << 4;
 
        mutex_init(&dev->lock);
        if (!request_region(dev->io, 8, "typhoon")) {
@@ -378,17 +378,17 @@ static int __init typhoon_init(void)
        dev->vdev.ioctl_ops = &typhoon_ioctl_ops;
        dev->vdev.release = video_device_release_empty;
        video_set_drvdata(&dev->vdev, dev);
+
+       /* mute card - prevents noisy bootups */
+       typhoon_mute(dev);
+
        if (video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
                v4l2_device_unregister(&dev->v4l2_dev);
                release_region(dev->io, 8);
                return -EINVAL;
        }
        v4l2_info(v4l2_dev, "port 0x%x.\n", dev->io);
-       v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", dev->mutefreq);
-       dev->mutefreq <<= 4;
-
-       /* mute card - prevents noisy bootups */
-       typhoon_mute(dev);
+       v4l2_info(v4l2_dev, "mute frequency is %lu kHz.\n", mutefreq);
 
        return 0;
 }
index f31eab99c943ba9cdc722e7b3163ed91f079d8a1..af99c5bd88c1f0ce15311ec63c137aeee2ce42ab 100644 (file)
@@ -377,7 +377,7 @@ static int vidioc_s_audio(struct file *file, void *priv,
 static const struct v4l2_file_operations zoltrix_fops =
 {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops zoltrix_ioctl_ops = {
@@ -424,20 +424,6 @@ static int __init zoltrix_init(void)
                return res;
        }
 
-       strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
-       zol->vdev.v4l2_dev = v4l2_dev;
-       zol->vdev.fops = &zoltrix_fops;
-       zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
-       zol->vdev.release = video_device_release_empty;
-       video_set_drvdata(&zol->vdev, zol);
-
-       if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
-               v4l2_device_unregister(v4l2_dev);
-               release_region(zol->io, 2);
-               return -EINVAL;
-       }
-       v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
-
        mutex_init(&zol->lock);
 
        /* mute card - prevents noisy bootups */
@@ -452,6 +438,20 @@ static int __init zoltrix_init(void)
        zol->curvol = 0;
        zol->stereo = 1;
 
+       strlcpy(zol->vdev.name, v4l2_dev->name, sizeof(zol->vdev.name));
+       zol->vdev.v4l2_dev = v4l2_dev;
+       zol->vdev.fops = &zoltrix_fops;
+       zol->vdev.ioctl_ops = &zoltrix_ioctl_ops;
+       zol->vdev.release = video_device_release_empty;
+       video_set_drvdata(&zol->vdev, zol);
+
+       if (video_register_device(&zol->vdev, VFL_TYPE_RADIO, radio_nr) < 0) {
+               v4l2_device_unregister(v4l2_dev);
+               release_region(zol->io, 2);
+               return -EINVAL;
+       }
+       v4l2_info(v4l2_dev, "Zoltrix Radio Plus card driver.\n");
+
        return 0;
 }
 
index 31e7a123d19a954f86808ec80ae8978fd044d3d8..f989f2820d88e90f49f5b4fc6081002126c0c3c2 100644 (file)
@@ -712,7 +712,7 @@ static int ar_initialize(struct ar *ar)
 static const struct v4l2_file_operations ar_fops = {
        .owner          = THIS_MODULE,
        .read           = ar_read,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops ar_ioctl_ops = {
index a529619e51f687d1386c6c673a0feaa9ba8d517a..0902ec041c7a71fd11842b3128de23dbb4ec5daf 100644 (file)
@@ -854,7 +854,6 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
                xbits |= RESOURCE_VIDEO_READ | RESOURCE_VIDEO_STREAM;
 
        /* is it free? */
-       mutex_lock(&btv->lock);
        if (btv->resources & xbits) {
                /* no, someone else uses it */
                goto fail;
@@ -884,11 +883,9 @@ int check_alloc_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bit)
        /* it's free, grab it */
        fh->resources  |= bit;
        btv->resources |= bit;
-       mutex_unlock(&btv->lock);
        return 1;
 
  fail:
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -940,7 +937,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
                /* trying to free ressources not allocated by us ... */
                printk("bttv: BUG! (btres)\n");
        }
-       mutex_lock(&btv->lock);
        fh->resources  &= ~bits;
        btv->resources &= ~bits;
 
@@ -951,8 +947,6 @@ void free_btres_lock(struct bttv *btv, struct bttv_fh *fh, int bits)
 
        if (0 == (bits & VBI_RESOURCES))
                disclaim_vbi_lines(btv);
-
-       mutex_unlock(&btv->lock);
 }
 
 /* ----------------------------------------------------------------------- */
@@ -1713,28 +1707,20 @@ static int bttv_prepare_buffer(struct videobuf_queue *q,struct bttv *btv,
 
                /* Make sure tvnorm and vbi_end remain consistent
                   until we're done. */
-               mutex_lock(&btv->lock);
 
                norm = btv->tvnorm;
 
                /* In this mode capturing always starts at defrect.top
                   (default VDELAY), ignoring cropping parameters. */
                if (btv->vbi_end > bttv_tvnorms[norm].cropcap.defrect.top) {
-                       mutex_unlock(&btv->lock);
                        return -EINVAL;
                }
 
-               mutex_unlock(&btv->lock);
-
                c.rect = bttv_tvnorms[norm].cropcap.defrect;
        } else {
-               mutex_lock(&btv->lock);
-
                norm = btv->tvnorm;
                c = btv->crop[!!fh->do_crop];
 
-               mutex_unlock(&btv->lock);
-
                if (width < c.min_scaled_width ||
                    width > c.max_scaled_width ||
                    height < c.min_scaled_height)
@@ -1858,7 +1844,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
        unsigned int i;
        int err;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (err)
                goto err;
@@ -1874,7 +1859,6 @@ static int bttv_s_std(struct file *file, void *priv, v4l2_std_id *id)
        set_tvnorm(btv, i);
 
 err:
-       mutex_unlock(&btv->lock);
 
        return err;
 }
@@ -1898,7 +1882,6 @@ static int bttv_enum_input(struct file *file, void *priv,
        struct bttv *btv = fh->btv;
        int rc = 0;
 
-       mutex_lock(&btv->lock);
        if (i->index >= bttv_tvcards[btv->c.type].video_inputs) {
                rc = -EINVAL;
                goto err;
@@ -1928,7 +1911,6 @@ static int bttv_enum_input(struct file *file, void *priv,
        i->std = BTTV_NORMS;
 
 err:
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -1938,9 +1920,7 @@ static int bttv_g_input(struct file *file, void *priv, unsigned int *i)
        struct bttv_fh *fh = priv;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        *i = btv->input;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -1952,7 +1932,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
 
        int err;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (unlikely(err))
                goto err;
@@ -1965,7 +1944,6 @@ static int bttv_s_input(struct file *file, void *priv, unsigned int i)
        set_input(btv, i, btv->tvnorm);
 
 err:
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -1979,7 +1957,6 @@ static int bttv_s_tuner(struct file *file, void *priv,
        if (unlikely(0 != t->index))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        if (unlikely(btv->tuner_type == TUNER_ABSENT)) {
                err = -EINVAL;
                goto err;
@@ -1995,7 +1972,6 @@ static int bttv_s_tuner(struct file *file, void *priv,
                btv->audio_mode_gpio(btv, t, 1);
 
 err:
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2006,10 +1982,8 @@ static int bttv_g_frequency(struct file *file, void *priv,
        struct bttv_fh *fh  = priv;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        f->type = btv->radio_user ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
        f->frequency = btv->freq;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2024,7 +1998,6 @@ static int bttv_s_frequency(struct file *file, void *priv,
        if (unlikely(f->tuner != 0))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        err = v4l2_prio_check(&btv->prio, fh->prio);
        if (unlikely(err))
                goto err;
@@ -2039,7 +2012,6 @@ static int bttv_s_frequency(struct file *file, void *priv,
        if (btv->has_matchbox && btv->radio_user)
                tea5757_set_freq(btv, btv->freq);
 err:
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2172,7 +2144,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
 
        /* Make sure tvnorm, vbi_end and the current cropping parameters
           remain consistent until we're done. */
-       mutex_lock(&btv->lock);
 
        b = &bttv_tvnorms[btv->tvnorm].cropcap.bounds;
 
@@ -2250,7 +2221,6 @@ limit_scaled_size_lock       (struct bttv_fh *               fh,
        rc = 0; /* success */
 
  fail:
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -2282,9 +2252,7 @@ verify_window_lock                (struct bttv_fh *               fh,
        if (V4L2_FIELD_ANY == field) {
                __s32 height2;
 
-               mutex_lock(&fh->btv->lock);
                height2 = fh->btv->crop[!!fh->do_crop].rect.height >> 1;
-               mutex_unlock(&fh->btv->lock);
                field = (win->w.height > height2)
                        ? V4L2_FIELD_INTERLACED
                        : V4L2_FIELD_TOP;
@@ -2360,7 +2328,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
                }
        }
 
-       mutex_lock(&fh->cap.vb_lock);
        /* clip against screen */
        if (NULL != btv->fbuf.base)
                n = btcx_screen_clips(btv->fbuf.fmt.width, btv->fbuf.fmt.height,
@@ -2391,13 +2358,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
        fh->ov.field    = win->field;
        fh->ov.setup_ok = 1;
 
-       /*
-        * FIXME: btv is protected by btv->lock mutex, while btv->init
-        *        is protected by fh->cap.vb_lock. This seems to open the
-        *        possibility for some race situations. Maybe the better would
-        *        be to unify those locks or to use another way to store the
-        *        init values that will be consumed by videobuf callbacks
-        */
        btv->init.ov.w.width   = win->w.width;
        btv->init.ov.w.height  = win->w.height;
        btv->init.ov.field     = win->field;
@@ -2412,7 +2372,6 @@ static int setup_window_lock(struct bttv_fh *fh, struct bttv *btv,
                bttv_overlay_risc(btv, &fh->ov, fh->ovfmt, new);
                retval = bttv_switch_overlay(btv,fh,new);
        }
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2526,9 +2485,7 @@ static int bttv_try_fmt_vid_cap(struct file *file, void *priv,
        if (V4L2_FIELD_ANY == field) {
                __s32 height2;
 
-               mutex_lock(&btv->lock);
                height2 = btv->crop[!!fh->do_crop].rect.height >> 1;
-               mutex_unlock(&btv->lock);
                field = (f->fmt.pix.height > height2)
                        ? V4L2_FIELD_INTERLACED
                        : V4L2_FIELD_BOTTOM;
@@ -2614,7 +2571,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
        fmt = format_by_fourcc(f->fmt.pix.pixelformat);
 
        /* update our state informations */
-       mutex_lock(&fh->cap.vb_lock);
        fh->fmt              = fmt;
        fh->cap.field        = f->fmt.pix.field;
        fh->cap.last         = V4L2_FIELD_NONE;
@@ -2623,7 +2579,6 @@ static int bttv_s_fmt_vid_cap(struct file *file, void *priv,
        btv->init.fmt        = fmt;
        btv->init.width      = f->fmt.pix.width;
        btv->init.height     = f->fmt.pix.height;
-       mutex_unlock(&fh->cap.vb_lock);
 
        return 0;
 }
@@ -2649,11 +2604,9 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
        unsigned int i;
        struct bttv_fh *fh = priv;
 
-       mutex_lock(&fh->cap.vb_lock);
        retval = __videobuf_mmap_setup(&fh->cap, gbuffers, gbufsize,
                                     V4L2_MEMORY_MMAP);
        if (retval < 0) {
-               mutex_unlock(&fh->cap.vb_lock);
                return retval;
        }
 
@@ -2665,7 +2618,6 @@ static int vidiocgmbuf(struct file *file, void *priv, struct video_mbuf *mbuf)
        for (i = 0; i < gbuffers; i++)
                mbuf->offsets[i] = i * gbufsize;
 
-       mutex_unlock(&fh->cap.vb_lock);
        return 0;
 }
 #endif
@@ -2775,10 +2727,8 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
        int retval = 0;
 
        if (on) {
-               mutex_lock(&fh->cap.vb_lock);
                /* verify args */
                if (unlikely(!btv->fbuf.base)) {
-                       mutex_unlock(&fh->cap.vb_lock);
                        return -EINVAL;
                }
                if (unlikely(!fh->ov.setup_ok)) {
@@ -2787,13 +2737,11 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
                }
                if (retval)
                        return retval;
-               mutex_unlock(&fh->cap.vb_lock);
        }
 
        if (!check_alloc_btres_lock(btv, fh, RESOURCE_OVERLAY))
                return -EBUSY;
 
-       mutex_lock(&fh->cap.vb_lock);
        if (on) {
                fh->ov.tvnorm = btv->tvnorm;
                new = videobuf_sg_alloc(sizeof(*new));
@@ -2805,7 +2753,6 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
 
        /* switch over */
        retval = bttv_switch_overlay(btv, fh, new);
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2844,7 +2791,6 @@ static int bttv_s_fbuf(struct file *file, void *f,
        }
 
        /* ok, accept it */
-       mutex_lock(&fh->cap.vb_lock);
        btv->fbuf.base       = fb->base;
        btv->fbuf.fmt.width  = fb->fmt.width;
        btv->fbuf.fmt.height = fb->fmt.height;
@@ -2876,7 +2822,6 @@ static int bttv_s_fbuf(struct file *file, void *f,
                        retval = bttv_switch_overlay(btv, fh, new);
                }
        }
-       mutex_unlock(&fh->cap.vb_lock);
        return retval;
 }
 
@@ -2955,7 +2900,6 @@ static int bttv_queryctrl(struct file *file, void *priv,
             c->id >= V4L2_CID_PRIVATE_LASTP1))
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        if (!btv->volume_gpio && (c->id == V4L2_CID_AUDIO_VOLUME))
                *c = no_ctl;
        else {
@@ -2963,7 +2907,6 @@ static int bttv_queryctrl(struct file *file, void *priv,
 
                *c = (NULL != ctrl) ? *ctrl : no_ctl;
        }
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2974,10 +2917,8 @@ static int bttv_g_parm(struct file *file, void *f,
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        v4l2_video_std_frame_period(bttv_tvnorms[btv->tvnorm].v4l2_id,
                                    &parm->parm.capture.timeperframe);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -2993,7 +2934,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
        if (0 != t->index)
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        t->rxsubchans = V4L2_TUNER_SUB_MONO;
        bttv_call_all(btv, tuner, g_tuner, t);
        strcpy(t->name, "Television");
@@ -3005,7 +2945,6 @@ static int bttv_g_tuner(struct file *file, void *priv,
        if (btv->audio_mode_gpio)
                btv->audio_mode_gpio(btv, t, 0);
 
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3014,9 +2953,7 @@ static int bttv_g_priority(struct file *file, void *f, enum v4l2_priority *p)
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        *p = v4l2_prio_max(&btv->prio);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3028,9 +2965,7 @@ static int bttv_s_priority(struct file *file, void *f,
        struct bttv *btv = fh->btv;
        int     rc;
 
-       mutex_lock(&btv->lock);
        rc = v4l2_prio_change(&btv->prio, &fh->prio, prio);
-       mutex_unlock(&btv->lock);
 
        return rc;
 }
@@ -3045,9 +2980,7 @@ static int bttv_cropcap(struct file *file, void *priv,
            cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
                return -EINVAL;
 
-       mutex_lock(&btv->lock);
        *cap = bttv_tvnorms[btv->tvnorm].cropcap;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3065,9 +2998,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
           inconsistent with fh->width or fh->height and apps
           do not expect a change here. */
 
-       mutex_lock(&btv->lock);
        crop->c = btv->crop[!!fh->do_crop].rect;
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3091,17 +3022,14 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
        /* Make sure tvnorm, vbi_end and the current cropping
           parameters remain consistent until we're done. Note
           read() may change vbi_end in check_alloc_btres_lock(). */
-       mutex_lock(&btv->lock);
        retval = v4l2_prio_check(&btv->prio, fh->prio);
        if (0 != retval) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
        retval = -EBUSY;
 
        if (locked_btres(fh->btv, VIDEO_RESOURCES)) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
@@ -3113,7 +3041,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
        b_top = max(b->top, btv->vbi_end);
        if (b_top + 32 >= b_bottom) {
-               mutex_unlock(&btv->lock);
                return retval;
        }
 
@@ -3136,12 +3063,8 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
 
        btv->crop[1] = c;
 
-       mutex_unlock(&btv->lock);
-
        fh->do_crop = 1;
 
-       mutex_lock(&fh->cap.vb_lock);
-
        if (fh->width < c.min_scaled_width) {
                fh->width = c.min_scaled_width;
                btv->init.width = c.min_scaled_width;
@@ -3158,8 +3081,6 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
                btv->init.height = c.max_scaled_height;
        }
 
-       mutex_unlock(&fh->cap.vb_lock);
-
        return 0;
 }
 
@@ -3227,7 +3148,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
                return videobuf_poll_stream(file, &fh->vbi, wait);
        }
 
-       mutex_lock(&fh->cap.vb_lock);
        if (check_btres(fh,RESOURCE_VIDEO_STREAM)) {
                /* streaming capture */
                if (list_empty(&fh->cap.stream))
@@ -3262,7 +3182,6 @@ static unsigned int bttv_poll(struct file *file, poll_table *wait)
        else
                rc = 0;
 err:
-       mutex_unlock(&fh->cap.vb_lock);
        return rc;
 }
 
@@ -3293,23 +3212,11 @@ static int bttv_open(struct file *file)
                return -ENOMEM;
        file->private_data = fh;
 
-       /*
-        * btv is protected by btv->lock mutex, while btv->init and other
-        * streaming vars are protected by fh->cap.vb_lock. We need to take
-        * care of both locks to avoid troubles. However, vb_lock is used also
-        * inside videobuf, without calling buf->lock. So, it is a very bad
-        * idea to hold both locks at the same time.
-        * Let's first copy btv->init at fh, holding cap.vb_lock, and then work
-        * with the rest of init, holding btv->lock.
-        */
-       mutex_lock(&fh->cap.vb_lock);
        *fh = btv->init;
-       mutex_unlock(&fh->cap.vb_lock);
 
        fh->type = type;
        fh->ov.setup_ok = 0;
 
-       mutex_lock(&btv->lock);
        v4l2_prio_open(&btv->prio, &fh->prio);
 
        videobuf_queue_sg_init(&fh->cap, &bttv_video_qops,
@@ -3317,13 +3224,13 @@ static int bttv_open(struct file *file)
                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
                            V4L2_FIELD_INTERLACED,
                            sizeof(struct bttv_buffer),
-                           fh, NULL);
+                           fh, &btv->lock);
        videobuf_queue_sg_init(&fh->vbi, &bttv_vbi_qops,
                            &btv->c.pci->dev, &btv->s_lock,
                            V4L2_BUF_TYPE_VBI_CAPTURE,
                            V4L2_FIELD_SEQ_TB,
                            sizeof(struct bttv_buffer),
-                           fh, NULL);
+                           fh, &btv->lock);
        set_tvnorm(btv,btv->tvnorm);
        set_input(btv, btv->input, btv->tvnorm);
 
@@ -3346,7 +3253,6 @@ static int bttv_open(struct file *file)
        bttv_vbi_fmt_reset(&fh->vbi_fmt, btv->tvnorm);
 
        bttv_field_count(btv);
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3355,7 +3261,6 @@ static int bttv_release(struct file *file)
        struct bttv_fh *fh = file->private_data;
        struct bttv *btv = fh->btv;
 
-       mutex_lock(&btv->lock);
        /* turn off overlay */
        if (check_btres(fh, RESOURCE_OVERLAY))
                bttv_switch_overlay(btv,fh,NULL);
@@ -3381,14 +3286,8 @@ static int bttv_release(struct file *file)
 
        /* free stuff */
 
-       /*
-        * videobuf uses cap.vb_lock - we should avoid holding btv->lock,
-        * otherwise we may have dead lock conditions
-        */
-       mutex_unlock(&btv->lock);
        videobuf_mmap_free(&fh->cap);
        videobuf_mmap_free(&fh->vbi);
-       mutex_lock(&btv->lock);
        v4l2_prio_close(&btv->prio, fh->prio);
        file->private_data = NULL;
        kfree(fh);
@@ -3398,7 +3297,6 @@ static int bttv_release(struct file *file)
 
        if (!btv->users)
                audio_mute(btv, 1);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3502,11 +3400,8 @@ static int radio_open(struct file *file)
        if (unlikely(!fh))
                return -ENOMEM;
        file->private_data = fh;
-       mutex_lock(&fh->cap.vb_lock);
        *fh = btv->init;
-       mutex_unlock(&fh->cap.vb_lock);
 
-       mutex_lock(&btv->lock);
        v4l2_prio_open(&btv->prio, &fh->prio);
 
        btv->radio_user++;
@@ -3514,7 +3409,6 @@ static int radio_open(struct file *file)
        bttv_call_all(btv, tuner, s_radio);
        audio_input(btv,TVAUDIO_INPUT_RADIO);
 
-       mutex_unlock(&btv->lock);
        return 0;
 }
 
@@ -3524,7 +3418,6 @@ static int radio_release(struct file *file)
        struct bttv *btv = fh->btv;
        struct rds_command cmd;
 
-       mutex_lock(&btv->lock);
        v4l2_prio_close(&btv->prio, fh->prio);
        file->private_data = NULL;
        kfree(fh);
@@ -3532,7 +3425,6 @@ static int radio_release(struct file *file)
        btv->radio_user--;
 
        bttv_call_all(btv, core, ioctl, RDS_CMD_CLOSE, &cmd);
-       mutex_unlock(&btv->lock);
 
        return 0;
 }
@@ -3561,7 +3453,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
                return -EINVAL;
        if (0 != t->index)
                return -EINVAL;
-       mutex_lock(&btv->lock);
        strcpy(t->name, "Radio");
        t->type = V4L2_TUNER_RADIO;
 
@@ -3570,8 +3461,6 @@ static int radio_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
        if (btv->audio_mode_gpio)
                btv->audio_mode_gpio(btv, t, 0);
 
-       mutex_unlock(&btv->lock);
-
        return 0;
 }
 
@@ -3692,7 +3581,7 @@ static const struct v4l2_file_operations radio_fops =
        .open     = radio_open,
        .read     = radio_read,
        .release  = radio_release,
-       .ioctl    = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll     = radio_poll,
 };
 
index 935e0c9a96744aa1e4f0cd3d443c8ee4c8b407d2..c1193506131c3a37e3c347a8703771a98f3938af 100644 (file)
@@ -860,7 +860,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = qcam_read,
 };
 
index 6e4b19698c13fe6212ee08cfd0d9bee7be3cf964..24fc00965a12d048be055498230b734b794283fa 100644 (file)
@@ -718,7 +718,7 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations qcam_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = qcam_read,
 };
 
index 260c666ce9317266fb271ffead70ea1605e99db1..0dfff50891e404056059eaf18316bd81fed0824f 100644 (file)
@@ -1775,7 +1775,7 @@ static const struct v4l2_file_operations cafe_v4l_fops = {
        .read = cafe_v4l_read,
        .poll = cafe_v4l_poll,
        .mmap = cafe_v4l_mmap,
-       .ioctl = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops cafe_v4l_ioctl_ops = {
index 8f55692db36d278e01191bd3fd2ea9e380c90965..82d195be91976ad18ae3cb9059e64efcf2c44788 100644 (file)
@@ -218,7 +218,13 @@ static int snd_cx18_pcm_capture_close(struct snd_pcm_substream *substream)
 static int snd_cx18_pcm_ioctl(struct snd_pcm_substream *substream,
                     unsigned int cmd, void *arg)
 {
-       return snd_pcm_lib_ioctl(substream, cmd, arg);
+       struct snd_cx18_card *cxsc = snd_pcm_substream_chip(substream);
+       int ret;
+
+       snd_cx18_lock(cxsc);
+       ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+       snd_cx18_unlock(cxsc);
+       return ret;
 }
 
 
index 9045f1ece0ebb35cdb1b85eec68b96cc2344fcfc..ab461e27d9dd1ad6206e9054f391605556563a74 100644 (file)
@@ -41,7 +41,7 @@ static struct v4l2_file_operations cx18_v4l2_enc_fops = {
        .read = cx18_v4l2_read,
        .open = cx18_v4l2_open,
        /* FIXME change to video_ioctl2 if serialization lock can be removed */
-       .ioctl = cx18_v4l2_ioctl,
+       .unlocked_ioctl = cx18_v4l2_ioctl,
        .release = cx18_v4l2_close,
        .poll = cx18_v4l2_enc_poll,
 };
index dfb198d0415bc200b0152c1be105d722261653c5..f16461844c5c0063e281da22b8cd3e27fe6d28f4 100644 (file)
@@ -1989,8 +1989,23 @@ static int cx25840_probe(struct i2c_client *client,
        v4l2_ctrl_new_std(&state->hdl, &cx25840_ctrl_ops,
                        V4L2_CID_HUE, -128, 127, 1, 0);
        if (!is_cx2583x(state)) {
-               default_volume = 228 - cx25840_read(client, 0x8d4);
-               default_volume = ((default_volume / 2) + 23) << 9;
+               default_volume = cx25840_read(client, 0x8d4);
+               /*
+                * Enforce the legacy PVR-350/MSP3400 to PVR-150/CX25843 volume
+                * scale mapping limits to avoid -ERANGE errors when
+                * initializing the volume control
+                */
+               if (default_volume > 228) {
+                       /* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
+                       default_volume = 228;
+                       cx25840_write(client, 0x8d4, 228);
+               }
+               else if (default_volume < 20) {
+                       /* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
+                       default_volume = 20;
+                       cx25840_write(client, 0x8d4, 20);
+               }
+               default_volume = (((228 - default_volume) >> 1) + 23) << 9;
 
                state->volume = v4l2_ctrl_new_std(&state->hdl,
                        &cx25840_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
index 4aaa47c0eabf54ea8e008a616b0dac531b423ce7..54b7fcd469a8a9b2db267e81ac163d0e579ce31b 100644 (file)
@@ -40,7 +40,6 @@
 #include <sound/control.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
-#include <media/wm8775.h>
 
 #include "cx88.h"
 #include "cx88-reg.h"
@@ -587,47 +586,26 @@ static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
        int left, right, v, b;
        int changed = 0;
        u32 old;
-       struct v4l2_control client_ctl;
-
-       /* Pass volume & balance onto any WM8775 */
-       if (value->value.integer.value[0] >= value->value.integer.value[1]) {
-               v = value->value.integer.value[0] << 10;
-               b = value->value.integer.value[0] ?
-                       (0x8000 * value->value.integer.value[1]) / value->value.integer.value[0] :
-                       0x8000;
-       } else {
-               v = value->value.integer.value[1] << 10;
-               b = value->value.integer.value[1] ?
-               0xffff - (0x8000 * value->value.integer.value[0]) / value->value.integer.value[1] :
-               0x8000;
-       }
-       client_ctl.value = v;
-       client_ctl.id = V4L2_CID_AUDIO_VOLUME;
-       call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
-       client_ctl.value = b;
-       client_ctl.id = V4L2_CID_AUDIO_BALANCE;
-       call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
 
        left = value->value.integer.value[0] & 0x3f;
        right = value->value.integer.value[1] & 0x3f;
        b = right - left;
        if (b < 0) {
-               v = 0x3f - left;
-               b = (-b) | 0x40;
+           v = 0x3f - left;
+           b = (-b) | 0x40;
        } else {
-               v = 0x3f - right;
+           v = 0x3f - right;
        }
        /* Do we really know this will always be called with IRQs on? */
        spin_lock_irq(&chip->reg_lock);
        old = cx_read(AUD_VOL_CTL);
        if (v != (old & 0x3f)) {
-               cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
-               changed = 1;
+           cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
+           changed = 1;
        }
-       if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
-               cx_write(AUD_BAL_CTL, b);
-               changed = 1;
+       if (cx_read(AUD_BAL_CTL) != b) {
+           cx_write(AUD_BAL_CTL, b);
+           changed = 1;
        }
        spin_unlock_irq(&chip->reg_lock);
 
@@ -640,7 +618,7 @@ static const struct snd_kcontrol_new snd_cx88_volume = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
                  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-       .name = "Analog-TV Volume",
+       .name = "Playback Volume",
        .info = snd_cx88_volume_info,
        .get = snd_cx88_volume_get,
        .put = snd_cx88_volume_put,
@@ -671,14 +649,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
        vol = cx_read(AUD_VOL_CTL);
        if (value->value.integer.value[0] != !(vol & bit)) {
                vol ^= bit;
-               cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
-               /* Pass mute onto any WM8775 */
-               if ((1<<6) == bit) {
-                       struct v4l2_control client_ctl;
-                       client_ctl.value = 0 != (vol & bit);
-                       client_ctl.id = V4L2_CID_AUDIO_MUTE;
-                       call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-               }
+               cx_write(AUD_VOL_CTL, vol);
                ret = 1;
        }
        spin_unlock_irq(&chip->reg_lock);
@@ -687,7 +658,7 @@ static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol,
 
 static const struct snd_kcontrol_new snd_cx88_dac_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Audio-Out Switch",
+       .name = "Playback Switch",
        .info = snd_ctl_boolean_mono_info,
        .get = snd_cx88_switch_get,
        .put = snd_cx88_switch_put,
@@ -696,49 +667,13 @@ static const struct snd_kcontrol_new snd_cx88_dac_switch = {
 
 static const struct snd_kcontrol_new snd_cx88_source_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Analog-TV Switch",
+       .name = "Capture Switch",
        .info = snd_ctl_boolean_mono_info,
        .get = snd_cx88_switch_get,
        .put = snd_cx88_switch_put,
        .private_value = (1<<6),
 };
 
-static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
-                              struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core = chip->core;
-       struct v4l2_control client_ctl;
-
-       client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
-       call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
-       value->value.integer.value[0] = client_ctl.value ? 1 : 0;
-
-       return 0;
-}
-
-static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
-                                      struct snd_ctl_elem_value *value)
-{
-       snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
-       struct cx88_core *core = chip->core;
-       struct v4l2_control client_ctl;
-
-       client_ctl.value = 0 != value->value.integer.value[0];
-       client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
-       call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
-       return 0;
-}
-
-static struct snd_kcontrol_new snd_cx88_alc_switch = {
-       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-       .name = "Line-In ALC Switch",
-       .info = snd_ctl_boolean_mono_info,
-       .get = snd_cx88_alc_get,
-       .put = snd_cx88_alc_put,
-};
-
 /****************************************************************************
                        Basic Flow for Sound Devices
  ****************************************************************************/
@@ -860,7 +795,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
 {
        struct snd_card  *card;
        snd_cx88_card_t  *chip;
-       struct v4l2_subdev *sd;
        int              err;
 
        if (devno >= SNDRV_CARDS)
@@ -896,15 +830,6 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
        if (err < 0)
                goto error;
 
-       /* If there's a wm8775 then add a Line-In ALC switch */
-       list_for_each_entry(sd, &chip->core->v4l2_dev.subdevs, list) {
-               if (WM8775_GID == sd->grp_id) {
-                       snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch,
-                                                      chip));
-                       break;
-               }
-       }
-
        strcpy (card->driver, "CX88x");
        sprintf(card->shortname, "Conexant CX%x", pci->device);
        sprintf(card->longname, "%s at %#llx",
index 9b9e169cce90862ee92f7d80ab7851cdb3cf81cb..0ccc2afd72668e7d2b8384312b01cde4ebb0e86b 100644 (file)
@@ -1007,15 +1007,22 @@ static const struct cx88_board cx88_boards[] = {
                .radio_type     = UNSET,
                .tuner_addr     = ADDR_UNSET,
                .radio_addr     = ADDR_UNSET,
+               .audio_chip = V4L2_IDENT_WM8775,
                .input          = {{
                        .type   = CX88_VMUX_DVB,
                        .vmux   = 0,
+                       /* 2: Line-In */
+                       .audioroute = 2,
                },{
                        .type   = CX88_VMUX_COMPOSITE1,
                        .vmux   = 1,
+                       /* 2: Line-In */
+                       .audioroute = 2,
                },{
                        .type   = CX88_VMUX_SVIDEO,
                        .vmux   = 2,
+                       /* 2: Line-In */
+                       .audioroute = 2,
                }},
                .mpeg           = CX88_MPEG_DVB,
        },
index 62cea9549404bf29d3d58e004af015dcb132f779..d9249e5a04c9088041a67d9a1b997e26dae64761 100644 (file)
@@ -40,7 +40,6 @@
 #include "cx88.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
-#include <media/wm8775.h>
 
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -977,7 +976,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
        const struct cx88_ctrl *c = NULL;
        u32 value,mask;
        int i;
-       struct v4l2_control client_ctl;
 
        for (i = 0; i < CX8800_CTLS; i++) {
                if (cx8800_ctls[i].v.id == ctl->id) {
@@ -991,27 +989,6 @@ int cx88_set_control(struct cx88_core *core, struct v4l2_control *ctl)
                ctl->value = c->v.minimum;
        if (ctl->value > c->v.maximum)
                ctl->value = c->v.maximum;
-
-       /* Pass changes onto any WM8775 */
-       client_ctl.id = ctl->id;
-       switch (ctl->id) {
-       case V4L2_CID_AUDIO_MUTE:
-               client_ctl.value = ctl->value;
-               break;
-       case V4L2_CID_AUDIO_VOLUME:
-               client_ctl.value = (ctl->value) ?
-                       (0x90 + ctl->value) << 8 : 0;
-               break;
-       case V4L2_CID_AUDIO_BALANCE:
-               client_ctl.value = ctl->value << 9;
-               break;
-       default:
-               client_ctl.id = 0;
-               break;
-       }
-       if (client_ctl.id)
-               call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
-
        mask=c->mask;
        switch (ctl->id) {
        case V4L2_CID_AUDIO_BALANCE:
@@ -1558,9 +1535,7 @@ static int radio_queryctrl (struct file *file, void *priv,
        if (c->id <  V4L2_CID_BASE ||
                c->id >= V4L2_CID_LASTP1)
                return -EINVAL;
-       if (c->id == V4L2_CID_AUDIO_MUTE ||
-               c->id == V4L2_CID_AUDIO_VOLUME ||
-               c->id == V4L2_CID_AUDIO_BALANCE) {
+       if (c->id == V4L2_CID_AUDIO_MUTE) {
                for (i = 0; i < CX8800_CTLS; i++) {
                        if (cx8800_ctls[i].v.id == c->id)
                                break;
index e8c732e7ae4f612dfc5004d7f56ba5bd9b9a8d53..c9981e77416a6f8292721b53333bd9cbba1da35c 100644 (file)
@@ -398,19 +398,17 @@ static inline struct cx88_core *to_core(struct v4l2_device *v4l2_dev)
        return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
 }
 
-#define call_hw(core, grpid, o, f, args...) \
+#define call_all(core, o, f, args...)                          \
        do {                                                    \
                if (!core->i2c_rc) {                            \
                        if (core->gate_ctrl)                    \
                                core->gate_ctrl(core, 1);       \
-                       v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
+                       v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \
                        if (core->gate_ctrl)                    \
                                core->gate_ctrl(core, 0);       \
                }                                               \
        } while (0)
 
-#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
-
 struct cx8800_dev;
 struct cx8802_dev;
 
index 908e3bc88303989c10f6ae8950286a820d2132e9..2c3007280032ea5472e45e9b1c75ee38aaa36b4c 100644 (file)
@@ -2377,7 +2377,7 @@ static const struct v4l2_file_operations radio_fops = {
        .owner         = THIS_MODULE,
        .open          = em28xx_v4l2_open,
        .release       = em28xx_v4l2_close,
-       .ioctl         = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
index a5cfc76b40b71e26dcc68e41f1f0b8acdf128e51..bb164099ea2c866a4a250664dbd7f06ddf48767c 100644 (file)
@@ -2530,7 +2530,7 @@ static const struct v4l2_file_operations et61x251_fops = {
        .owner = THIS_MODULE,
        .open =    et61x251_open,
        .release = et61x251_release,
-       .ioctl =   et61x251_ioctl,
+       .unlocked_ioctl =   et61x251_ioctl,
        .read =    et61x251_read,
        .poll =    et61x251_poll,
        .mmap =    et61x251_mmap,
index 330dadc001064e1a477e16acd65723ad72adcc76..e23de57e2c73de5d3c575eb4f52ae2a96be3259c 100644 (file)
@@ -63,7 +63,10 @@ struct sd {
 #define QUALITY_DEF 80
        u8 jpegqual;                    /* webcam quality */
 
+       u8 reg01;
+       u8 reg17;
        u8 reg18;
+       u8 flags;
 
        s8 ag_cnt;
 #define AG_CNT_START 13
@@ -96,6 +99,22 @@ enum sensors {
        SENSOR_SP80708,
 };
 
+/* device flags */
+#define PDN_INV        1               /* inverse pin S_PWR_DN / sn_xxx tables */
+
+/* sn9c1xx definitions */
+/* register 0x01 */
+#define S_PWR_DN       0x01    /* sensor power down */
+#define S_PDN_INV      0x02    /* inverse pin S_PWR_DN */
+#define V_TX_EN                0x04    /* video transfer enable */
+#define LED            0x08    /* output to pin LED */
+#define SCL_SEL_OD     0x20    /* open-drain mode */
+#define SYS_SEL_48M    0x40    /* system clock 0: 24MHz, 1: 48MHz */
+/* register 0x17 */
+#define MCK_SIZE_MASK  0x1f    /* sensor master clock */
+#define SEN_CLK_EN     0x20    /* enable sensor clock */
+#define DEF_EN         0x80    /* defect pixel by 0: soft, 1: hard */
+
 /* V4L2 controls supported by the driver */
 static void setbrightness(struct gspca_dev *gspca_dev);
 static void setcontrast(struct gspca_dev *gspca_dev);
@@ -1755,141 +1774,6 @@ static void po2030n_probe(struct gspca_dev *gspca_dev)
        }
 }
 
-static void bridge_init(struct gspca_dev *gspca_dev,
-                         const u8 *sn9c1xx)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       u8 reg0102[2];
-       const u8 *reg9a;
-       static const u8 reg9a_def[] =
-               {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
-       static const u8 reg9a_spec[] =
-               {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
-       static const u8 regd4[] = {0x60, 0x00, 0x00};
-
-       /* sensor clock already enabled in sd_init */
-       /* reg_w1(gspca_dev, 0xf1, 0x00); */
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-
-       /* configure gpio */
-       reg0102[0] = sn9c1xx[1];
-       reg0102[1] = sn9c1xx[2];
-       if (gspca_dev->audio)
-               reg0102[1] |= 0x04;     /* keep the audio connection */
-       reg_w(gspca_dev, 0x01, reg0102, 2);
-       reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
-       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
-       switch (sd->sensor) {
-       case SENSOR_GC0307:
-       case SENSOR_OV7660:
-       case SENSOR_PO1030:
-       case SENSOR_PO2030N:
-       case SENSOR_SOI768:
-       case SENSOR_SP80708:
-               reg9a = reg9a_spec;
-               break;
-       default:
-               reg9a = reg9a_def;
-               break;
-       }
-       reg_w(gspca_dev, 0x9a, reg9a, 6);
-
-       reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
-
-       reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
-
-       switch (sd->sensor) {
-       case SENSOR_ADCM1700:
-               reg_w1(gspca_dev, 0x01, 0x43);
-               reg_w1(gspca_dev, 0x17, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_GC0307:
-               msleep(50);
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x22);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               msleep(50);
-               break;
-       case SENSOR_MI0360B:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_MT9V111:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x61);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_OM6802:
-               msleep(10);
-               reg_w1(gspca_dev, 0x02, 0x73);
-               reg_w1(gspca_dev, 0x17, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x22);
-               msleep(100);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x17, 0x64);
-               reg_w1(gspca_dev, 0x17, 0x64);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               msleep(10);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               i2c_w8(gspca_dev, om6802_init0[0]);
-               i2c_w8(gspca_dev, om6802_init0[1]);
-               msleep(15);
-               reg_w1(gspca_dev, 0x02, 0x71);
-               msleep(150);
-               break;
-       case SENSOR_OV7630:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0xe2);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_OV7648:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_PO1030:
-       case SENSOR_SOI768:
-               reg_w1(gspca_dev, 0x01, 0x61);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x60);
-               reg_w1(gspca_dev, 0x01, 0x40);
-               break;
-       case SENSOR_PO2030N:
-       case SENSOR_OV7660:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               break;
-       case SENSOR_SP80708:
-               reg_w1(gspca_dev, 0x01, 0x63);
-               reg_w1(gspca_dev, 0x17, 0x20);
-               reg_w1(gspca_dev, 0x01, 0x62);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               msleep(100);
-               reg_w1(gspca_dev, 0x02, 0x62);
-               break;
-       default:
-/*     case SENSOR_HV7131R: */
-/*     case SENSOR_MI0360: */
-/*     case SENSOR_MO4000: */
-               reg_w1(gspca_dev, 0x01, 0x43);
-               reg_w1(gspca_dev, 0x17, 0x61);
-               reg_w1(gspca_dev, 0x01, 0x42);
-               if (sd->sensor == SENSOR_HV7131R)
-                       hv7131r_probe(gspca_dev);
-               break;
-       }
-}
-
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
                        const struct usb_device_id *id)
@@ -1898,7 +1782,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        sd->bridge = id->driver_info >> 16;
-       sd->sensor = id->driver_info;
+       sd->sensor = id->driver_info >> 8;
+       sd->flags = id->driver_info;
 
        cam = &gspca_dev->cam;
        if (sd->sensor == SENSOR_ADCM1700) {
@@ -1929,7 +1814,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
        /* setup a selector by bridge */
        reg_w1(gspca_dev, 0xf1, 0x01);
        reg_r(gspca_dev, 0x00, 1);
-       reg_w1(gspca_dev, 0xf1, gspca_dev->usb_buf[0]);
+       reg_w1(gspca_dev, 0xf1, 0x00);
        reg_r(gspca_dev, 0x00, 1);              /* get sonix chip id */
        regF1 = gspca_dev->usb_buf[0];
        if (gspca_dev->usb_err < 0)
@@ -2423,10 +2308,17 @@ static int sd_start(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int i;
-       u8 reg1, reg17;
+       u8 reg01, reg17;
+       u8 reg0102[2];
        const u8 *sn9c1xx;
        const u8 (*init)[8];
+       const u8 *reg9a;
        int mode;
+       static const u8 reg9a_def[] =
+               {0x00, 0x40, 0x20, 0x00, 0x00, 0x00};
+       static const u8 reg9a_spec[] =
+               {0x00, 0x40, 0x38, 0x30, 0x00, 0x20};
+       static const u8 regd4[] = {0x60, 0x00, 0x00};
        static const u8 C0[] = { 0x2d, 0x2d, 0x3a, 0x05, 0x04, 0x3f };
        static const u8 CA[] = { 0x28, 0xd8, 0x14, 0xec };
        static const u8 CA_adcm1700[] =
@@ -2448,7 +2340,85 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        /* initialize the bridge */
        sn9c1xx = sn_tb[sd->sensor];
-       bridge_init(gspca_dev, sn9c1xx);
+
+       /* sensor clock already enabled in sd_init */
+       /* reg_w1(gspca_dev, 0xf1, 0x00); */
+       reg01 = sn9c1xx[1];
+       if (sd->flags & PDN_INV)
+               reg01 ^= S_PDN_INV;             /* power down inverted */
+       reg_w1(gspca_dev, 0x01, reg01);
+
+       /* configure gpio */
+       reg0102[0] = reg01;
+       reg0102[1] = sn9c1xx[2];
+       if (gspca_dev->audio)
+               reg0102[1] |= 0x04;     /* keep the audio connection */
+       reg_w(gspca_dev, 0x01, reg0102, 2);
+       reg_w(gspca_dev, 0x08, &sn9c1xx[8], 2);
+       reg_w(gspca_dev, 0x17, &sn9c1xx[0x17], 5);
+       switch (sd->sensor) {
+       case SENSOR_GC0307:
+       case SENSOR_OV7660:
+       case SENSOR_PO1030:
+       case SENSOR_PO2030N:
+       case SENSOR_SOI768:
+       case SENSOR_SP80708:
+               reg9a = reg9a_spec;
+               break;
+       default:
+               reg9a = reg9a_def;
+               break;
+       }
+       reg_w(gspca_dev, 0x9a, reg9a, 6);
+
+       reg_w(gspca_dev, 0xd4, regd4, sizeof regd4);
+
+       reg_w(gspca_dev, 0x03, &sn9c1xx[3], 0x0f);
+
+       reg17 = sn9c1xx[0x17];
+       switch (sd->sensor) {
+       case SENSOR_GC0307:
+               msleep(50);             /*fixme: is it useful? */
+               break;
+       case SENSOR_OM6802:
+               msleep(10);
+               reg_w1(gspca_dev, 0x02, 0x73);
+               reg17 |= SEN_CLK_EN;
+               reg_w1(gspca_dev, 0x17, reg17);
+               reg_w1(gspca_dev, 0x01, 0x22);
+               msleep(100);
+               reg01 = SCL_SEL_OD | S_PDN_INV;
+               reg17 &= MCK_SIZE_MASK;
+               reg17 |= 0x04;          /* clock / 4 */
+               break;
+       }
+       reg01 |= SYS_SEL_48M;
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg17 |= SEN_CLK_EN;
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg01 &= ~S_PWR_DN;             /* sensor power on */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 &= ~SYS_SEL_48M;
+       reg_w1(gspca_dev, 0x01, reg01);
+
+       switch (sd->sensor) {
+       case SENSOR_HV7131R:
+               hv7131r_probe(gspca_dev);       /*fixme: is it useful? */
+               break;
+       case SENSOR_OM6802:
+               msleep(10);
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, om6802_init0[0]);
+               i2c_w8(gspca_dev, om6802_init0[1]);
+               msleep(15);
+               reg_w1(gspca_dev, 0x02, 0x71);
+               msleep(150);
+               break;
+       case SENSOR_SP80708:
+               msleep(100);
+               reg_w1(gspca_dev, 0x02, 0x62);
+               break;
+       }
 
        /* initialize the sensor */
        i2c_w_seq(gspca_dev, sensor_init[sd->sensor]);
@@ -2476,30 +2446,11 @@ static int sd_start(struct gspca_dev *gspca_dev)
        }
        reg_w1(gspca_dev, 0x18, sn9c1xx[0x18]);
        switch (sd->sensor) {
-       case SENSOR_GC0307:
-               reg17 = 0xa2;
-               break;
-       case SENSOR_MT9V111:
-       case SENSOR_MI0360B:
-               reg17 = 0xe0;
-               break;
-       case SENSOR_ADCM1700:
-       case SENSOR_OV7630:
-               reg17 = 0xe2;
-               break;
-       case SENSOR_OV7648:
-               reg17 = 0x20;
-               break;
-       case SENSOR_OV7660:
-       case SENSOR_SOI768:
-               reg17 = 0xa0;
-               break;
-       case SENSOR_PO1030:
-       case SENSOR_PO2030N:
-               reg17 = 0xa0;
+       case SENSOR_OM6802:
+/*     case SENSOR_OV7648:             * fixme: sometimes */
                break;
        default:
-               reg17 = 0x60;
+               reg17 |= DEF_EN;
                break;
        }
        reg_w1(gspca_dev, 0x17, reg17);
@@ -2546,95 +2497,67 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        init = NULL;
        mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-       if (mode)
-               reg1 = 0x46;    /* 320x240: clk 48Mhz, video trf enable */
-       else
-               reg1 = 0x06;    /* 640x480: clk 24Mhz, video trf enable */
-       reg17 = 0x61;           /* 0x:20: enable sensor clock */
+       reg01 |= SYS_SEL_48M | V_TX_EN;
+       reg17 &= ~MCK_SIZE_MASK;
+       reg17 |= 0x02;                  /* clock / 2 */
        switch (sd->sensor) {
        case SENSOR_ADCM1700:
                init = adcm1700_sensor_param1;
-               reg1 = 0x46;
-               reg17 = 0xe2;
                break;
        case SENSOR_GC0307:
                init = gc0307_sensor_param1;
-               reg17 = 0xa2;
-               reg1 = 0x44;
+               break;
+       case SENSOR_HV7131R:
+       case SENSOR_MI0360:
+               if (mode)
+                       reg01 |= SYS_SEL_48M;   /* 320x240: clk 48Mhz */
+               else
+                       reg01 &= ~SYS_SEL_48M;  /* 640x480: clk 24Mhz */
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x01;                  /* clock / 1 */
                break;
        case SENSOR_MI0360B:
                init = mi0360b_sensor_param1;
-               reg1 &= ~0x02;          /* don't inverse pin S_PWR_DN */
-               reg17 = 0xe2;
                break;
        case SENSOR_MO4000:
-               if (mode) {
-/*                     reg1 = 0x46;     * 320 clk 48Mhz 60fp/s */
-                       reg1 = 0x06;    /* clk 24Mz */
-               } else {
-                       reg17 = 0x22;   /* 640 MCKSIZE */
-/*                     reg1 = 0x06;     * 640 clk 24Mz (done) */
+               if (mode) {                     /* if 320x240 */
+                       reg01 &= ~SYS_SEL_48M;  /* clk 24Mz */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x01;          /* clock / 1 */
                }
                break;
        case SENSOR_MT9V111:
                init = mt9v111_sensor_param1;
-               if (mode) {
-                       reg1 = 0x04;    /* 320 clk 48Mhz */
-               } else {
-/*                     reg1 = 0x06;     * 640 clk 24Mz (done) */
-                       reg17 = 0xc2;
-               }
                break;
        case SENSOR_OM6802:
                init = om6802_sensor_param1;
-               reg17 = 0x64;           /* 640 MCKSIZE */
+               if (!mode) {                    /* if 640x480 */
+                       reg17 &= ~MCK_SIZE_MASK;
+                       reg17 |= 0x01;          /* clock / 4 */
+               }
                break;
        case SENSOR_OV7630:
                init = ov7630_sensor_param1;
-               reg17 = 0xe2;
-               reg1 = 0x44;
                break;
        case SENSOR_OV7648:
                init = ov7648_sensor_param1;
-               reg17 = 0x21;
-/*             reg1 = 0x42;             * 42 - 46? */
+               reg17 &= ~MCK_SIZE_MASK;
+               reg17 |= 0x01;                  /* clock / 1 */
                break;
        case SENSOR_OV7660:
                init = ov7660_sensor_param1;
-               if (sd->bridge == BRIDGE_SN9C120) {
-                       if (mode) {             /* 320x240 - 160x120 */
-                               reg17 = 0xa2;
-                               reg1 = 0x44;    /* 48 Mhz, video trf eneble */
-                       }
-               } else {
-                       reg17 = 0x22;
-                       reg1 = 0x06;    /* 24 Mhz, video trf eneble
-                                        * inverse power down */
-               }
                break;
        case SENSOR_PO1030:
                init = po1030_sensor_param1;
-               reg17 = 0xa2;
-               reg1 = 0x44;
                break;
        case SENSOR_PO2030N:
                init = po2030n_sensor_param1;
-               reg1 = 0x46;
-               reg17 = 0xa2;
                break;
        case SENSOR_SOI768:
                init = soi768_sensor_param1;
-               reg1 = 0x44;
-               reg17 = 0xa2;
                break;
        case SENSOR_SP80708:
                init = sp80708_sensor_param1;
-               if (mode) {
-/*??                   reg1 = 0x04;     * 320 clk 48Mhz */
-               } else {
-                       reg1 = 0x46;     /* 640 clk 48Mz */
-                       reg17 = 0xa2;
-               }
                break;
        }
 
@@ -2684,7 +2607,9 @@ static int sd_start(struct gspca_dev *gspca_dev)
        setjpegqual(gspca_dev);
 
        reg_w1(gspca_dev, 0x17, reg17);
-       reg_w1(gspca_dev, 0x01, reg1);
+       reg_w1(gspca_dev, 0x01, reg01);
+       sd->reg01 = reg01;
+       sd->reg17 = reg17;
 
        sethvflip(gspca_dev);
        setbrightness(gspca_dev);
@@ -2706,41 +2631,64 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
                { 0xa1, 0x21, 0x76, 0x20, 0x00, 0x00, 0x00, 0x10 };
        static const u8 stopsoi768[] =
                { 0xa1, 0x21, 0x12, 0x80, 0x00, 0x00, 0x00, 0x10 };
-       u8 data;
-       const u8 *sn9c1xx;
+       u8 reg01;
+       u8 reg17;
 
-       data = 0x0b;
+       reg01 = sd->reg01;
+       reg17 = sd->reg17 & ~SEN_CLK_EN;
        switch (sd->sensor) {
+       case SENSOR_ADCM1700:
        case SENSOR_GC0307:
-               data = 0x29;
+       case SENSOR_PO2030N:
+       case SENSOR_SP80708:
+               reg01 |= LED;
+               reg_w1(gspca_dev, 0x01, reg01);
+               reg01 &= ~(LED | V_TX_EN);
+               reg_w1(gspca_dev, 0x01, reg01);
+/*             reg_w1(gspca_dev, 0x02, 0x??);   * LED off ? */
                break;
        case SENSOR_HV7131R:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
                i2c_w8(gspca_dev, stophv7131);
-               data = 0x2b;
                break;
        case SENSOR_MI0360:
        case SENSOR_MI0360B:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+/*             reg_w1(gspca_dev, 0x02, 0x40);    * LED off ? */
                i2c_w8(gspca_dev, stopmi0360);
-               data = 0x29;
                break;
-       case SENSOR_OV7648:
-               i2c_w8(gspca_dev, stopov7648);
-               /* fall thru */
        case SENSOR_MT9V111:
-       case SENSOR_OV7630:
+       case SENSOR_OM6802:
        case SENSOR_PO1030:
-               data = 0x29;
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               break;
+       case SENSOR_OV7630:
+       case SENSOR_OV7648:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
+               i2c_w8(gspca_dev, stopov7648);
+               break;
+       case SENSOR_OV7660:
+               reg01 &= ~V_TX_EN;
+               reg_w1(gspca_dev, 0x01, reg01);
                break;
        case SENSOR_SOI768:
                i2c_w8(gspca_dev, stopsoi768);
-               data = 0x29;
                break;
        }
-       sn9c1xx = sn_tb[sd->sensor];
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-       reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
-       reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
-       reg_w1(gspca_dev, 0x01, data);
+
+       reg01 |= SCL_SEL_OD;
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 |= S_PWR_DN;              /* sensor power down */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg_w1(gspca_dev, 0x17, reg17);
+       reg01 &= ~SYS_SEL_48M;          /* clock 24MHz */
+       reg_w1(gspca_dev, 0x01, reg01);
+       reg01 |= LED;
+       reg_w1(gspca_dev, 0x01, reg01);
        /* Don't disable sensor clock as that disables the button on the cam */
        /* reg_w1(gspca_dev, 0xf1, 0x01); */
 }
@@ -2954,14 +2902,18 @@ static const struct sd_desc sd_desc = {
 /* -- module initialisation -- */
 #define BS(bridge, sensor) \
        .driver_info = (BRIDGE_ ## bridge << 16) \
-                       | SENSOR_ ## sensor
+                       | (SENSOR_ ## sensor << 8)
+#define BSF(bridge, sensor, flags) \
+       .driver_info = (BRIDGE_ ## bridge << 16) \
+                       | (SENSOR_ ## sensor << 8) \
+                       | (flags)
 static const __devinitdata struct usb_device_id device_table[] = {
 #if !defined CONFIG_USB_SN9C102 && !defined CONFIG_USB_SN9C102_MODULE
        {USB_DEVICE(0x0458, 0x7025), BS(SN9C120, MI0360)},
        {USB_DEVICE(0x0458, 0x702e), BS(SN9C120, OV7660)},
 #endif
-       {USB_DEVICE(0x045e, 0x00f5), BS(SN9C105, OV7660)},
-       {USB_DEVICE(0x045e, 0x00f7), BS(SN9C105, OV7660)},
+       {USB_DEVICE(0x045e, 0x00f5), BSF(SN9C105, OV7660, PDN_INV)},
+       {USB_DEVICE(0x045e, 0x00f7), BSF(SN9C105, OV7660, PDN_INV)},
        {USB_DEVICE(0x0471, 0x0327), BS(SN9C105, MI0360)},
        {USB_DEVICE(0x0471, 0x0328), BS(SN9C105, MI0360)},
        {USB_DEVICE(0x0471, 0x0330), BS(SN9C105, MI0360)},
index 2be23bccd3c89e9a72b1131cb6bf1804df1434d0..48d2c2419c13134abf0c55cdf347bdfd97c897bd 100644 (file)
@@ -1659,7 +1659,7 @@ static const struct v4l2_file_operations meye_fops = {
        .open           = meye_open,
        .release        = meye_release,
        .mmap           = meye_mmap,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .poll           = meye_poll,
 };
 
@@ -1831,12 +1831,6 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        msleep(1);
        mchip_set(MCHIP_MM_INTA, MCHIP_MM_INTA_HIC_1_MASK);
 
-       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
-                                 video_nr) < 0) {
-               v4l2_err(v4l2_dev, "video_register_device failed\n");
-               goto outvideoreg;
-       }
-
        mutex_init(&meye.lock);
        init_waitqueue_head(&meye.proc_list);
        meye.brightness = 32 << 10;
@@ -1858,6 +1852,12 @@ static int __devinit meye_probe(struct pci_dev *pcidev,
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAPICTURE, 0);
        sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERAAGC, 48);
 
+       if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
+                                 video_nr) < 0) {
+               v4l2_err(v4l2_dev, "video_register_device failed\n");
+               goto outvideoreg;
+       }
+
        v4l2_info(v4l2_dev, "Motion Eye Camera Driver v%s.\n",
               MEYE_DRIVER_VERSION);
        v4l2_info(v4l2_dev, "mchip KL5A72002 rev. %d, base %lx, irq %d\n",
index 072bd2d1cfad46f4c5a25ea33f789409c2848a5c..13565cba237d13e0a99922067ceb9edb9edd1e83 100644 (file)
@@ -807,8 +807,6 @@ static int mx2_camera_set_bus_param(struct soc_camera_device *icd,
 
        if (common_flags & SOCAM_PCLK_SAMPLE_RISING)
                csicr1 |= CSICR1_REDGE;
-       if (common_flags & SOCAM_PCLK_SAMPLE_FALLING)
-               csicr1 |= CSICR1_INV_PCLK;
        if (common_flags & SOCAM_VSYNC_ACTIVE_HIGH)
                csicr1 |= CSICR1_SOF_POL;
        if (common_flags & SOCAM_HSYNC_ACTIVE_HIGH)
index 7129b50757dbd7605fa13449bd7793511019f52f..7551907f8c280f4b9f896094ea9fe0cc079bfd19 100644 (file)
@@ -932,7 +932,7 @@ static ssize_t pms_read(struct file *file, char __user *buf,
 
 static const struct v4l2_file_operations pms_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = pms_read,
 };
 
index 1b93207c89e84efbbf6a4e3e8357a7af7f32f90d..2f500809f53d9b418dd2d3117ce44ef7706d0287 100644 (file)
@@ -522,6 +522,7 @@ static int fimc_cap_streamon(struct file *file, void *priv,
        INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
        fimc->vid_cap.active_buf_cnt = 0;
        fimc->vid_cap.frame_count = 0;
+       fimc->vid_cap.buf_index = fimc_hw_get_frame_index(fimc);
 
        set_bit(ST_CAPT_PEND, &fimc->state);
        ret = videobuf_streamon(&fimc->vid_cap.vbq);
@@ -652,6 +653,50 @@ static int fimc_cap_s_ctrl(struct file *file, void *priv,
        return ret;
 }
 
+static int fimc_cap_cropcap(struct file *file, void *fh,
+                           struct v4l2_cropcap *cr)
+{
+       struct fimc_frame *f;
+       struct fimc_ctx *ctx = fh;
+       struct fimc_dev *fimc = ctx->fimc_dev;
+
+       if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (mutex_lock_interruptible(&fimc->lock))
+               return -ERESTARTSYS;
+
+       f = &ctx->s_frame;
+       cr->bounds.left         = 0;
+       cr->bounds.top          = 0;
+       cr->bounds.width        = f->o_width;
+       cr->bounds.height       = f->o_height;
+       cr->defrect             = cr->bounds;
+
+       mutex_unlock(&fimc->lock);
+       return 0;
+}
+
+static int fimc_cap_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+{
+       struct fimc_frame *f;
+       struct fimc_ctx *ctx = file->private_data;
+       struct fimc_dev *fimc = ctx->fimc_dev;
+
+
+       if (mutex_lock_interruptible(&fimc->lock))
+               return -ERESTARTSYS;
+
+       f = &ctx->s_frame;
+       cr->c.left      = f->offs_h;
+       cr->c.top       = f->offs_v;
+       cr->c.width     = f->width;
+       cr->c.height    = f->height;
+
+       mutex_unlock(&fimc->lock);
+       return 0;
+}
+
 static int fimc_cap_s_crop(struct file *file, void *fh,
                               struct v4l2_crop *cr)
 {
@@ -716,9 +761,9 @@ static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
        .vidioc_g_ctrl                  = fimc_vidioc_g_ctrl,
        .vidioc_s_ctrl                  = fimc_cap_s_ctrl,
 
-       .vidioc_g_crop                  = fimc_vidioc_g_crop,
+       .vidioc_g_crop                  = fimc_cap_g_crop,
        .vidioc_s_crop                  = fimc_cap_s_crop,
-       .vidioc_cropcap                 = fimc_vidioc_cropcap,
+       .vidioc_cropcap                 = fimc_cap_cropcap,
 
        .vidioc_enum_input              = fimc_cap_enum_input,
        .vidioc_s_input                 = fimc_cap_s_input,
@@ -785,7 +830,7 @@ int fimc_register_capture_device(struct fimc_dev *fimc)
        videobuf_queue_dma_contig_init(&vid_cap->vbq, &fimc_qops,
                vid_cap->v4l2_dev.dev, &fimc->irqlock,
                V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
-               sizeof(struct fimc_vid_buffer), (void *)ctx);
+               sizeof(struct fimc_vid_buffer), (void *)ctx, NULL);
 
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
        if (ret) {
index 2e7c547894b687d9fd37288e365ceae704dbcbfc..bb99f2d805d3347975e0ff32603bd2f7b8f44e20 100644 (file)
@@ -50,8 +50,8 @@ static struct fimc_fmt fimc_formats[] = {
                .planes_cnt = 1,
                .flags = FMT_FLAGS_M2M,
        }, {
-               .name = "XRGB-8-8-8-8, 24 bpp",
-               .fourcc = V4L2_PIX_FMT_RGB24,
+               .name = "XRGB-8-8-8-8, 32 bpp",
+               .fourcc = V4L2_PIX_FMT_RGB32,
                .depth = 32,
                .color  = S5P_FIMC_RGB888,
                .buff_cnt = 1,
@@ -983,6 +983,7 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv,
 {
        struct fimc_ctx *ctx = priv;
        struct v4l2_queryctrl *c;
+       int ret = -EINVAL;
 
        c = get_ctrl(qc->id);
        if (c) {
@@ -990,10 +991,14 @@ int fimc_vidioc_queryctrl(struct file *file, void *priv,
                return 0;
        }
 
-       if (ctx->state & FIMC_CTX_CAP)
-               return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
+       if (ctx->state & FIMC_CTX_CAP) {
+               if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
+                       return -ERESTARTSYS;
+               ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
                                        core, queryctrl, qc);
-       return -EINVAL;
+               mutex_unlock(&ctx->fimc_dev->lock);
+       }
+       return ret;
 }
 
 int fimc_vidioc_g_ctrl(struct file *file, void *priv,
@@ -1115,7 +1120,7 @@ static int fimc_m2m_s_ctrl(struct file *file, void *priv,
        return 0;
 }
 
-int fimc_vidioc_cropcap(struct file *file, void *fh,
+static int fimc_m2m_cropcap(struct file *file, void *fh,
                        struct v4l2_cropcap *cr)
 {
        struct fimc_frame *frame;
@@ -1139,7 +1144,7 @@ int fimc_vidioc_cropcap(struct file *file, void *fh,
        return 0;
 }
 
-int fimc_vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+static int fimc_m2m_g_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 {
        struct fimc_frame *frame;
        struct fimc_ctx *ctx = file->private_data;
@@ -1167,22 +1172,22 @@ int fimc_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
        struct fimc_frame *f;
        u32 min_size, halign;
 
-       f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
-               &ctx->s_frame : &ctx->d_frame;
-
        if (cr->c.top < 0 || cr->c.left < 0) {
                v4l2_err(&fimc->m2m.v4l2_dev,
                        "doesn't support negative values for top & left\n");
                return -EINVAL;
        }
 
-       f = ctx_get_frame(ctx, cr->type);
-       if (IS_ERR(f))
-               return PTR_ERR(f);
+       if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               f = (ctx->state & FIMC_CTX_CAP) ? &ctx->s_frame : &ctx->d_frame;
+       else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+                ctx->state & FIMC_CTX_M2M)
+               f = &ctx->s_frame;
+       else
+               return -EINVAL;
 
-       min_size = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-               ? fimc->variant->min_inp_pixsize
-               : fimc->variant->min_out_pixsize;
+       min_size = (f == &ctx->s_frame) ?
+               fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
 
        if (ctx->state & FIMC_CTX_M2M) {
                if (fimc->id == 1 && fimc->variant->pix_hoff)
@@ -1233,6 +1238,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
        f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
                &ctx->s_frame : &ctx->d_frame;
 
+       if (mutex_lock_interruptible(&fimc->lock))
+               return -ERESTARTSYS;
+
        spin_lock_irqsave(&ctx->slock, flags);
        if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) {
                /* Check to see if scaling ratio is within supported range */
@@ -1241,9 +1249,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
                else
                        ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
                if (ret) {
-                       spin_unlock_irqrestore(&ctx->slock, flags);
                        v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto scr_unlock;
                }
        }
        ctx->state |= FIMC_PARAMS;
@@ -1253,7 +1261,9 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
        f->width  = cr->c.width;
        f->height = cr->c.height;
 
+scr_unlock:
        spin_unlock_irqrestore(&ctx->slock, flags);
+       mutex_unlock(&fimc->lock);
        return 0;
 }
 
@@ -1285,9 +1295,9 @@ static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
        .vidioc_g_ctrl                  = fimc_vidioc_g_ctrl,
        .vidioc_s_ctrl                  = fimc_m2m_s_ctrl,
 
-       .vidioc_g_crop                  = fimc_vidioc_g_crop,
+       .vidioc_g_crop                  = fimc_m2m_g_crop,
        .vidioc_s_crop                  = fimc_m2m_s_crop,
-       .vidioc_cropcap                 = fimc_vidioc_cropcap
+       .vidioc_cropcap                 = fimc_m2m_cropcap
 
 };
 
@@ -1396,7 +1406,7 @@ static const struct v4l2_file_operations fimc_m2m_fops = {
        .open           = fimc_m2m_open,
        .release        = fimc_m2m_release,
        .poll           = fimc_m2m_poll,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .mmap           = fimc_m2m_mmap,
 };
 
@@ -1736,6 +1746,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
        .pix_hoff        = 1,
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
+       .has_cistatus2   = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 16,
        .hor_offs_align  = 1,
@@ -1745,6 +1756,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
 
 static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
        .pix_hoff        = 1,
+       .has_cistatus2   = 1,
        .min_inp_pixsize = 16,
        .min_out_pixsize = 16,
        .hor_offs_align  = 1,
index 3e107851656017adfc1a2567956a93e28fd43cd5..4f047d35f8ad9333ce3b4768836685b3d5f2f411 100644 (file)
 
 /*#define DEBUG*/
 
+#include <linux/sched.h>
 #include <linux/types.h>
+#include <linux/videodev2.h>
 #include <media/videobuf-core.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-mediabus.h>
 #include <media/s3c_fimc.h>
-#include <linux/videodev2.h>
+
 #include "regs-fimc.h"
 
 #define err(fmt, args...) \
@@ -369,6 +371,7 @@ struct fimc_pix_limit {
  * @pix_hoff: indicate whether horizontal offset is in pixels or in bytes
  * @has_inp_rot: set if has input rotator
  * @has_out_rot: set if has output rotator
+ * @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision
  * @pix_limit: pixel size constraints for the scaler
  * @min_inp_pixsize: minimum input pixel size
  * @min_out_pixsize: minimum output pixel size
@@ -379,6 +382,7 @@ struct samsung_fimc_variant {
        unsigned int    pix_hoff:1;
        unsigned int    has_inp_rot:1;
        unsigned int    has_out_rot:1;
+       unsigned int    has_cistatus2:1;
        struct fimc_pix_limit *pix_limit;
        u16             min_inp_pixsize;
        u16             min_out_pixsize;
@@ -554,11 +558,19 @@ static inline struct fimc_frame *ctx_get_frame(struct fimc_ctx *ctx,
        return frame;
 }
 
+/* Return an index to the buffer actually being written. */
 static inline u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
 {
-       u32 reg = readl(dev->regs + S5P_CISTATUS);
-       return (reg & S5P_CISTATUS_FRAMECNT_MASK) >>
-               S5P_CISTATUS_FRAMECNT_SHIFT;
+       u32 reg;
+
+       if (dev->variant->has_cistatus2) {
+               reg = readl(dev->regs + S5P_CISTATUS2) & 0x3F;
+               return reg > 0 ? --reg : reg;
+       } else {
+               reg = readl(dev->regs + S5P_CISTATUS);
+               return (reg & S5P_CISTATUS_FRAMECNT_MASK) >>
+                       S5P_CISTATUS_FRAMECNT_SHIFT;
+       }
 }
 
 /* -----------------------------------------------------*/
@@ -594,10 +606,6 @@ int fimc_vidioc_g_fmt(struct file *file, void *priv,
                      struct v4l2_format *f);
 int fimc_vidioc_try_fmt(struct file *file, void *priv,
                        struct v4l2_format *f);
-int fimc_vidioc_g_crop(struct file *file, void *fh,
-                      struct v4l2_crop *cr);
-int fimc_vidioc_cropcap(struct file *file, void *fh,
-                       struct v4l2_cropcap *cr);
 int fimc_vidioc_queryctrl(struct file *file, void *priv,
                          struct v4l2_queryctrl *qc);
 int fimc_vidioc_g_ctrl(struct file *file, void *priv,
index a57daedb5b5cf7099e273afb276759b4228fef42..57e33f84fcfa5fa4a4fd35d7eb9998e75ac1d003 100644 (file)
 #define S5P_CISTATUS_VVALID_A          (1 << 15)
 #define S5P_CISTATUS_VVALID_B          (1 << 14)
 
+/* Indexes to the last and the currently processed buffer. */
+#define S5P_CISTATUS2                  0x68
+
 /* Image capture control */
 #define S5P_CIIMGCPT                   0xc0
 #define S5P_CIIMGCPT_IMGCPTEN          (1 << 31)
index 5c209afb0ac8ddb434d5c6335c2661161e36aa5b..2486520582f2c576639a28bc231ccf847a472e4b 100644 (file)
@@ -1980,7 +1980,7 @@ static int __devinit sh_mobile_ceu_probe(struct platform_device *pdev)
                 * we complete the completion.
                 */
 
-               if (!csi2->driver || !csi2->driver->owner) {
+               if (!csi2->driver) {
                        complete(&wait.completion);
                        /* Either too late, or probing failed */
                        bus_unregister_notifier(&platform_bus_type, &wait.notifier);
index 4e5a8cf76dedf7807b5a11ef5369f3f86c3c537c..07cf0c6c7c1f7a210c3a078fc580ee68845535c6 100644 (file)
@@ -75,6 +75,7 @@ struct sh_vou_device {
        int pix_idx;
        struct videobuf_buffer *active;
        enum sh_vou_status status;
+       struct mutex fop_lock;
 };
 
 struct sh_vou_file {
@@ -235,7 +236,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb)
        vb->state = VIDEOBUF_NEEDS_INIT;
 }
 
-/* Locking: caller holds vq->vb_lock mutex */
+/* Locking: caller holds fop_lock mutex */
 static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
                            unsigned int *size)
 {
@@ -257,7 +258,7 @@ static int sh_vou_buf_setup(struct videobuf_queue *vq, unsigned int *count,
        return 0;
 }
 
-/* Locking: caller holds vq->vb_lock mutex */
+/* Locking: caller holds fop_lock mutex */
 static int sh_vou_buf_prepare(struct videobuf_queue *vq,
                              struct videobuf_buffer *vb,
                              enum v4l2_field field)
@@ -306,7 +307,7 @@ static int sh_vou_buf_prepare(struct videobuf_queue *vq,
        return 0;
 }
 
-/* Locking: caller holds vq->vb_lock mutex and vq->irqlock spinlock */
+/* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */
 static void sh_vou_buf_queue(struct videobuf_queue *vq,
                             struct videobuf_buffer *vb)
 {
@@ -1190,7 +1191,7 @@ static int sh_vou_open(struct file *file)
                                       V4L2_BUF_TYPE_VIDEO_OUTPUT,
                                       V4L2_FIELD_NONE,
                                       sizeof(struct videobuf_buffer), vdev,
-                                      NULL);
+                                      &vou_dev->fop_lock);
 
        return 0;
 }
@@ -1292,7 +1293,7 @@ static const struct v4l2_file_operations sh_vou_fops = {
        .owner          = THIS_MODULE,
        .open           = sh_vou_open,
        .release        = sh_vou_release,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .mmap           = sh_vou_mmap,
        .poll           = sh_vou_poll,
 };
@@ -1331,6 +1332,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
 
        INIT_LIST_HEAD(&vou_dev->queue);
        spin_lock_init(&vou_dev->lock);
+       mutex_init(&vou_dev->fop_lock);
        atomic_set(&vou_dev->use_count, 0);
        vou_dev->pdata = vou_pdata;
        vou_dev->status = SH_VOU_IDLE;
@@ -1388,6 +1390,7 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
                vdev->tvnorms |= V4L2_STD_PAL;
        vdev->v4l2_dev = &vou_dev->v4l2_dev;
        vdev->release = video_device_release;
+       vdev->lock = &vou_dev->fop_lock;
 
        vou_dev->vdev = vdev;
        video_set_drvdata(vdev, vou_dev);
index 28e19daadec953b879084ec539a17eed2da147a6..f49fbfb7dc1377800da49d0c723caa13a5d14e27 100644 (file)
@@ -3238,7 +3238,7 @@ static const struct v4l2_file_operations sn9c102_fops = {
        .owner = THIS_MODULE,
        .open = sn9c102_open,
        .release = sn9c102_release,
-       .ioctl = sn9c102_ioctl,
+       .unlocked_ioctl = sn9c102_ioctl,
        .read = sn9c102_read,
        .poll = sn9c102_poll,
        .mmap = sn9c102_mmap,
index 335120c2021bc2cdbf5de98b59f58cc001144ad5..052bd6dfa5a787033d445401ddb114bb40796732 100644 (file)
@@ -405,13 +405,13 @@ static int soc_camera_open(struct file *file)
                ret = soc_camera_set_fmt(icd, &f);
                if (ret < 0)
                        goto esfmt;
+
+               ici->ops->init_videobuf(&icd->vb_vidq, icd);
        }
 
        file->private_data = icd;
        dev_dbg(&icd->dev, "camera device open\n");
 
-       ici->ops->init_videobuf(&icd->vb_vidq, icd);
-
        mutex_unlock(&icd->video_lock);
 
        return 0;
index f169f77366771a925978e65a9eeae7c18d49b812..59f8a9ad3796c3ef5960b4e77f12a7269ea7b7b9 100644 (file)
@@ -785,7 +785,7 @@ static void __uvc_find_control(struct uvc_entity *entity, __u32 v4l2_id,
        }
 }
 
-struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
+static struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
        __u32 v4l2_id, struct uvc_control_mapping **mapping)
 {
        struct uvc_control *ctrl = NULL;
@@ -944,6 +944,52 @@ done:
        return ret;
 }
 
+/*
+ * Mapping V4L2 controls to UVC controls can be straighforward if done well.
+ * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
+ * must be grouped (for instance the Red Balance, Blue Balance and Do White
+ * Balance V4L2 controls use the White Balance Component UVC control) or
+ * otherwise translated. The approach we take here is to use a translation
+ * table for the controls that can be mapped directly, and handle the others
+ * manually.
+ */
+int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+       struct v4l2_querymenu *query_menu)
+{
+       struct uvc_menu_info *menu_info;
+       struct uvc_control_mapping *mapping;
+       struct uvc_control *ctrl;
+       u32 index = query_menu->index;
+       u32 id = query_menu->id;
+       int ret;
+
+       memset(query_menu, 0, sizeof(*query_menu));
+       query_menu->id = id;
+       query_menu->index = index;
+
+       ret = mutex_lock_interruptible(&chain->ctrl_mutex);
+       if (ret < 0)
+               return -ERESTARTSYS;
+
+       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
+       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       if (query_menu->index >= mapping->menu_count) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       menu_info = &mapping->menu_info[query_menu->index];
+       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
+
+done:
+       mutex_unlock(&chain->ctrl_mutex);
+       return ret;
+}
+
 
 /* --------------------------------------------------------------------------
  * Control transactions
index ed6d5449741c58cb7b546b8a09a0b21f82759794..f14581bd707f0155248f788382fe6452cad7198c 100644 (file)
@@ -89,6 +89,39 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
        queue->type = type;
 }
 
+/*
+ * Free the video buffers.
+ *
+ * This function must be called with the queue lock held.
+ */
+static int __uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       unsigned int i;
+
+       for (i = 0; i < queue->count; ++i) {
+               if (queue->buffer[i].vma_use_count != 0)
+                       return -EBUSY;
+       }
+
+       if (queue->count) {
+               vfree(queue->mem);
+               queue->count = 0;
+       }
+
+       return 0;
+}
+
+int uvc_free_buffers(struct uvc_video_queue *queue)
+{
+       int ret;
+
+       mutex_lock(&queue->mutex);
+       ret = __uvc_free_buffers(queue);
+       mutex_unlock(&queue->mutex);
+
+       return ret;
+}
+
 /*
  * Allocate the video buffers.
  *
@@ -110,7 +143,7 @@ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
 
        mutex_lock(&queue->mutex);
 
-       if ((ret = uvc_free_buffers(queue)) < 0)
+       if ((ret = __uvc_free_buffers(queue)) < 0)
                goto done;
 
        /* Bail out if no buffers should be allocated. */
@@ -151,28 +184,6 @@ done:
        return ret;
 }
 
-/*
- * Free the video buffers.
- *
- * This function must be called with the queue lock held.
- */
-int uvc_free_buffers(struct uvc_video_queue *queue)
-{
-       unsigned int i;
-
-       for (i = 0; i < queue->count; ++i) {
-               if (queue->buffer[i].vma_use_count != 0)
-                       return -EBUSY;
-       }
-
-       if (queue->count) {
-               vfree(queue->mem);
-               queue->count = 0;
-       }
-
-       return 0;
-}
-
 /*
  * Check if buffers have been allocated.
  */
@@ -368,6 +379,82 @@ done:
        return ret;
 }
 
+/*
+ * VMA operations.
+ */
+static void uvc_vm_open(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count++;
+}
+
+static void uvc_vm_close(struct vm_area_struct *vma)
+{
+       struct uvc_buffer *buffer = vma->vm_private_data;
+       buffer->vma_use_count--;
+}
+
+static const struct vm_operations_struct uvc_vm_ops = {
+       .open           = uvc_vm_open,
+       .close          = uvc_vm_close,
+};
+
+/*
+ * Memory-map a video buffer.
+ *
+ * This function implements video buffers memory mapping and is intended to be
+ * used by the device mmap handler.
+ */
+int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
+{
+       struct uvc_buffer *uninitialized_var(buffer);
+       struct page *page;
+       unsigned long addr, start, size;
+       unsigned int i;
+       int ret = 0;
+
+       start = vma->vm_start;
+       size = vma->vm_end - vma->vm_start;
+
+       mutex_lock(&queue->mutex);
+
+       for (i = 0; i < queue->count; ++i) {
+               buffer = &queue->buffer[i];
+               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+                       break;
+       }
+
+       if (i == queue->count || size != queue->buf_size) {
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /*
+        * VM_IO marks the area as being an mmaped region for I/O to a
+        * device. It also prevents the region from being core dumped.
+        */
+       vma->vm_flags |= VM_IO;
+
+       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
+       while (size > 0) {
+               page = vmalloc_to_page((void *)addr);
+               if ((ret = vm_insert_page(vma, start, page)) < 0)
+                       goto done;
+
+               start += PAGE_SIZE;
+               addr += PAGE_SIZE;
+               size -= PAGE_SIZE;
+       }
+
+       vma->vm_ops = &uvc_vm_ops;
+       vma->vm_private_data = buffer;
+       uvc_vm_open(vma);
+
+done:
+       mutex_unlock(&queue->mutex);
+       return ret;
+}
+
 /*
  * Poll the video queue.
  *
index 6d15de9b520437a4440dc8da2071efd0b91fe306..8cf61e8a634ffeb7cb23bfe004efc2c60053f1e8 100644 (file)
@@ -100,40 +100,6 @@ done:
  * V4L2 interface
  */
 
-/*
- * Mapping V4L2 controls to UVC controls can be straighforward if done well.
- * Most of the UVC controls exist in V4L2, and can be mapped directly. Some
- * must be grouped (for instance the Red Balance, Blue Balance and Do White
- * Balance V4L2 controls use the White Balance Component UVC control) or
- * otherwise translated. The approach we take here is to use a translation
- * table for the controls that can be mapped directly, and handle the others
- * manually.
- */
-static int uvc_v4l2_query_menu(struct uvc_video_chain *chain,
-       struct v4l2_querymenu *query_menu)
-{
-       struct uvc_menu_info *menu_info;
-       struct uvc_control_mapping *mapping;
-       struct uvc_control *ctrl;
-       u32 index = query_menu->index;
-       u32 id = query_menu->id;
-
-       ctrl = uvc_find_control(chain, query_menu->id, &mapping);
-       if (ctrl == NULL || mapping->v4l2_type != V4L2_CTRL_TYPE_MENU)
-               return -EINVAL;
-
-       if (query_menu->index >= mapping->menu_count)
-               return -EINVAL;
-
-       memset(query_menu, 0, sizeof(*query_menu));
-       query_menu->id = id;
-       query_menu->index = index;
-
-       menu_info = &mapping->menu_info[query_menu->index];
-       strlcpy(query_menu->name, menu_info->name, sizeof query_menu->name);
-       return 0;
-}
-
 /*
  * Find the frame interval closest to the requested frame interval for the
  * given frame format and size. This should be done by the device as part of
@@ -260,12 +226,14 @@ static int uvc_v4l2_try_format(struct uvc_streaming *stream,
         * developers test their webcams with the Linux driver as well as with
         * the Windows driver).
         */
+       mutex_lock(&stream->mutex);
        if (stream->dev->quirks & UVC_QUIRK_PROBE_EXTRAFIELDS)
                probe->dwMaxVideoFrameSize =
                        stream->ctrl.dwMaxVideoFrameSize;
 
        /* Probe the device. */
        ret = uvc_probe_video(stream, probe);
+       mutex_unlock(&stream->mutex);
        if (ret < 0)
                goto done;
 
@@ -289,14 +257,21 @@ done:
 static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        struct v4l2_format *fmt)
 {
-       struct uvc_format *format = stream->cur_format;
-       struct uvc_frame *frame = stream->cur_frame;
+       struct uvc_format *format;
+       struct uvc_frame *frame;
+       int ret = 0;
 
        if (fmt->type != stream->type)
                return -EINVAL;
 
-       if (format == NULL || frame == NULL)
-               return -EINVAL;
+       mutex_lock(&stream->mutex);
+       format = stream->cur_format;
+       frame = stream->cur_frame;
+
+       if (format == NULL || frame == NULL) {
+               ret = -EINVAL;
+               goto done;
+       }
 
        fmt->fmt.pix.pixelformat = format->fcc;
        fmt->fmt.pix.width = frame->wWidth;
@@ -307,7 +282,9 @@ static int uvc_v4l2_get_format(struct uvc_streaming *stream,
        fmt->fmt.pix.colorspace = format->colorspace;
        fmt->fmt.pix.priv = 0;
 
-       return 0;
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
 }
 
 static int uvc_v4l2_set_format(struct uvc_streaming *stream,
@@ -321,18 +298,24 @@ static int uvc_v4l2_set_format(struct uvc_streaming *stream,
        if (fmt->type != stream->type)
                return -EINVAL;
 
-       if (uvc_queue_allocated(&stream->queue))
-               return -EBUSY;
-
        ret = uvc_v4l2_try_format(stream, fmt, &probe, &format, &frame);
        if (ret < 0)
                return ret;
 
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_allocated(&stream->queue)) {
+               ret = -EBUSY;
+               goto done;
+       }
+
        memcpy(&stream->ctrl, &probe, sizeof probe);
        stream->cur_format = format;
        stream->cur_frame = frame;
 
-       return 0;
+done:
+       mutex_unlock(&stream->mutex);
+       return ret;
 }
 
 static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
@@ -343,7 +326,10 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
        if (parm->type != stream->type)
                return -EINVAL;
 
+       mutex_lock(&stream->mutex);
        numerator = stream->ctrl.dwFrameInterval;
+       mutex_unlock(&stream->mutex);
+
        denominator = 10000000;
        uvc_simplify_fraction(&numerator, &denominator, 8, 333);
 
@@ -370,7 +356,6 @@ static int uvc_v4l2_get_streamparm(struct uvc_streaming *stream,
 static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
                struct v4l2_streamparm *parm)
 {
-       struct uvc_frame *frame = stream->cur_frame;
        struct uvc_streaming_control probe;
        struct v4l2_fract timeperframe;
        uint32_t interval;
@@ -379,28 +364,36 @@ static int uvc_v4l2_set_streamparm(struct uvc_streaming *stream,
        if (parm->type != stream->type)
                return -EINVAL;
 
-       if (uvc_queue_streaming(&stream->queue))
-               return -EBUSY;
-
        if (parm->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                timeperframe = parm->parm.capture.timeperframe;
        else
                timeperframe = parm->parm.output.timeperframe;
 
-       memcpy(&probe, &stream->ctrl, sizeof probe);
        interval = uvc_fraction_to_interval(timeperframe.numerator,
                timeperframe.denominator);
-
        uvc_trace(UVC_TRACE_FORMAT, "Setting frame interval to %u/%u (%u).\n",
                timeperframe.numerator, timeperframe.denominator, interval);
-       probe.dwFrameInterval = uvc_try_frame_interval(frame, interval);
+
+       mutex_lock(&stream->mutex);
+
+       if (uvc_queue_streaming(&stream->queue)) {
+               mutex_unlock(&stream->mutex);
+               return -EBUSY;
+       }
+
+       memcpy(&probe, &stream->ctrl, sizeof probe);
+       probe.dwFrameInterval =
+               uvc_try_frame_interval(stream->cur_frame, interval);
 
        /* Probe the device with the new settings. */
        ret = uvc_probe_video(stream, &probe);
-       if (ret < 0)
+       if (ret < 0) {
+               mutex_unlock(&stream->mutex);
                return ret;
+       }
 
        memcpy(&stream->ctrl, &probe, sizeof probe);
+       mutex_unlock(&stream->mutex);
 
        /* Return the actual frame period. */
        timeperframe.numerator = probe.dwFrameInterval;
@@ -528,11 +521,9 @@ static int uvc_v4l2_release(struct file *file)
        if (uvc_has_privileges(handle)) {
                uvc_video_enable(stream, 0);
 
-               mutex_lock(&stream->queue.mutex);
                if (uvc_free_buffers(&stream->queue) < 0)
                        uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to "
                                        "free buffers.\n");
-               mutex_unlock(&stream->queue.mutex);
        }
 
        /* Release the file handle. */
@@ -624,7 +615,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        }
 
        case VIDIOC_QUERYMENU:
-               return uvc_v4l2_query_menu(chain, arg);
+               return uvc_query_v4l2_menu(chain, arg);
 
        case VIDIOC_G_EXT_CTRLS:
        {
@@ -905,15 +896,17 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_CROPCAP:
        {
                struct v4l2_cropcap *ccap = arg;
-               struct uvc_frame *frame = stream->cur_frame;
 
                if (ccap->type != stream->type)
                        return -EINVAL;
 
                ccap->bounds.left = 0;
                ccap->bounds.top = 0;
-               ccap->bounds.width = frame->wWidth;
-               ccap->bounds.height = frame->wHeight;
+
+               mutex_lock(&stream->mutex);
+               ccap->bounds.width = stream->cur_frame->wWidth;
+               ccap->bounds.height = stream->cur_frame->wHeight;
+               mutex_unlock(&stream->mutex);
 
                ccap->defrect = ccap->bounds;
 
@@ -930,8 +923,6 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        case VIDIOC_REQBUFS:
        {
                struct v4l2_requestbuffers *rb = arg;
-               unsigned int bufsize =
-                       stream->ctrl.dwMaxVideoFrameSize;
 
                if (rb->type != stream->type ||
                    rb->memory != V4L2_MEMORY_MMAP)
@@ -940,7 +931,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if ((ret = uvc_acquire_privileges(handle)) < 0)
                        return ret;
 
-               ret = uvc_alloc_buffers(&stream->queue, rb->count, bufsize);
+               mutex_lock(&stream->mutex);
+               ret = uvc_alloc_buffers(&stream->queue, rb->count,
+                                       stream->ctrl.dwMaxVideoFrameSize);
+               mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
 
@@ -988,7 +982,9 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                if (!uvc_has_privileges(handle))
                        return -EBUSY;
 
+               mutex_lock(&stream->mutex);
                ret = uvc_video_enable(stream, 1);
+               mutex_unlock(&stream->mutex);
                if (ret < 0)
                        return ret;
                break;
@@ -1068,79 +1064,14 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
        return -EINVAL;
 }
 
-/*
- * VMA operations.
- */
-static void uvc_vm_open(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count++;
-}
-
-static void uvc_vm_close(struct vm_area_struct *vma)
-{
-       struct uvc_buffer *buffer = vma->vm_private_data;
-       buffer->vma_use_count--;
-}
-
-static const struct vm_operations_struct uvc_vm_ops = {
-       .open           = uvc_vm_open,
-       .close          = uvc_vm_close,
-};
-
 static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct uvc_fh *handle = file->private_data;
        struct uvc_streaming *stream = handle->stream;
-       struct uvc_video_queue *queue = &stream->queue;
-       struct uvc_buffer *uninitialized_var(buffer);
-       struct page *page;
-       unsigned long addr, start, size;
-       unsigned int i;
-       int ret = 0;
 
        uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
 
-       start = vma->vm_start;
-       size = vma->vm_end - vma->vm_start;
-
-       mutex_lock(&queue->mutex);
-
-       for (i = 0; i < queue->count; ++i) {
-               buffer = &queue->buffer[i];
-               if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
-                       break;
-       }
-
-       if (i == queue->count || size != queue->buf_size) {
-               ret = -EINVAL;
-               goto done;
-       }
-
-       /*
-        * VM_IO marks the area as being an mmaped region for I/O to a
-        * device. It also prevents the region from being core dumped.
-        */
-       vma->vm_flags |= VM_IO;
-
-       addr = (unsigned long)queue->mem + buffer->buf.m.offset;
-       while (size > 0) {
-               page = vmalloc_to_page((void *)addr);
-               if ((ret = vm_insert_page(vma, start, page)) < 0)
-                       goto done;
-
-               start += PAGE_SIZE;
-               addr += PAGE_SIZE;
-               size -= PAGE_SIZE;
-       }
-
-       vma->vm_ops = &uvc_vm_ops;
-       vma->vm_private_data = buffer;
-       uvc_vm_open(vma);
-
-done:
-       mutex_unlock(&queue->mutex);
-       return ret;
+       return uvc_queue_mmap(&stream->queue, vma);
 }
 
 static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
@@ -1157,7 +1088,7 @@ const struct v4l2_file_operations uvc_fops = {
        .owner          = THIS_MODULE,
        .open           = uvc_v4l2_open,
        .release        = uvc_v4l2_release,
-       .ioctl          = uvc_v4l2_ioctl,
+       .unlocked_ioctl = uvc_v4l2_ioctl,
        .read           = uvc_v4l2_read,
        .mmap           = uvc_v4l2_mmap,
        .poll           = uvc_v4l2_poll,
index 5555f01028385b3287952a53d45b2477db021582..5673d673504b838f510966c31c46c078da032bdd 100644 (file)
@@ -293,8 +293,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
        unsigned int i;
        int ret;
 
-       mutex_lock(&stream->mutex);
-
        /* Perform probing. The device should adjust the requested values
         * according to its capabilities. However, some devices, namely the
         * first generation UVC Logitech webcams, don't implement the Video
@@ -346,7 +344,6 @@ int uvc_probe_video(struct uvc_streaming *stream,
        }
 
 done:
-       mutex_unlock(&stream->mutex);
        return ret;
 }
 
index d97cf6d6a4f96c5ef6da3c3b48de0c83652ace70..45f01e7e13d2f90abd30466c8390c8fcecc4fb5a 100644 (file)
@@ -436,7 +436,9 @@ struct uvc_streaming {
        struct uvc_streaming_control ctrl;
        struct uvc_format *cur_format;
        struct uvc_frame *cur_frame;
-
+       /* Protect access to ctrl, cur_format, cur_frame and hardware video
+        * probe control.
+        */
        struct mutex mutex;
 
        unsigned int frozen : 1;
@@ -574,6 +576,8 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
 extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
 extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
                struct uvc_buffer *buf);
+extern int uvc_queue_mmap(struct uvc_video_queue *queue,
+               struct vm_area_struct *vma);
 extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
                struct file *file, poll_table *wait);
 extern int uvc_queue_allocated(struct uvc_video_queue *queue);
@@ -606,10 +610,10 @@ extern int uvc_status_suspend(struct uvc_device *dev);
 extern int uvc_status_resume(struct uvc_device *dev);
 
 /* Controls */
-extern struct uvc_control *uvc_find_control(struct uvc_video_chain *chain,
-               __u32 v4l2_id, struct uvc_control_mapping **mapping);
 extern int uvc_query_v4l2_ctrl(struct uvc_video_chain *chain,
                struct v4l2_queryctrl *v4l2_ctrl);
+extern int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
+               struct v4l2_querymenu *query_menu);
 
 extern int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
                const struct uvc_control_mapping *mapping);
index 03f7f4670e9badd4491f8cddb8e748a848c14119..359e23290a7e99ae0301a6d6844a445343cb900e 100644 (file)
@@ -186,12 +186,12 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = -EIO;
+       int ret = -ENODEV;
 
        if (!vdev->fops->read)
                return -EINVAL;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->read(filp, buf, sz, off);
        if (vdev->lock)
@@ -203,12 +203,12 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
                size_t sz, loff_t *off)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = -EIO;
+       int ret = -ENODEV;
 
        if (!vdev->fops->write)
                return -EINVAL;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->write(filp, buf, sz, off);
        if (vdev->lock)
@@ -219,10 +219,10 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
 static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = DEFAULT_POLLMASK;
+       int ret = POLLERR | POLLHUP;
 
        if (!vdev->fops->poll)
-               return ret;
+               return DEFAULT_POLLMASK;
        if (vdev->lock)
                mutex_lock(vdev->lock);
        if (video_is_registered(vdev))
@@ -238,20 +238,45 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        int ret = -ENODEV;
 
        if (vdev->fops->unlocked_ioctl) {
-               if (vdev->lock)
-                       mutex_lock(vdev->lock);
+               if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+                       return -ERESTARTSYS;
                if (video_is_registered(vdev))
                        ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
                if (vdev->lock)
                        mutex_unlock(vdev->lock);
        } else if (vdev->fops->ioctl) {
-               /* TODO: convert all drivers to unlocked_ioctl */
+               /* This code path is a replacement for the BKL. It is a major
+                * hack but it will have to do for those drivers that are not
+                * yet converted to use unlocked_ioctl.
+                *
+                * There are two options: if the driver implements struct
+                * v4l2_device, then the lock defined there is used to
+                * serialize the ioctls. Otherwise the v4l2 core lock defined
+                * below is used. This lock is really bad since it serializes
+                * completely independent devices.
+                *
+                * Both variants suffer from the same problem: if the driver
+                * sleeps, then it blocks all ioctls since the lock is still
+                * held. This is very common for VIDIOC_DQBUF since that
+                * normally waits for a frame to arrive. As a result any other
+                * ioctl calls will proceed very, very slowly since each call
+                * will have to wait for the VIDIOC_QBUF to finish. Things that
+                * should take 0.01s may now take 10-20 seconds.
+                *
+                * The workaround is to *not* take the lock for VIDIOC_DQBUF.
+                * This actually works OK for videobuf-based drivers, since
+                * videobuf will take its own internal lock.
+                */
                static DEFINE_MUTEX(v4l2_ioctl_mutex);
+               struct mutex *m = vdev->v4l2_dev ?
+                       &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex;
 
-               mutex_lock(&v4l2_ioctl_mutex);
+               if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m))
+                       return -ERESTARTSYS;
                if (video_is_registered(vdev))
                        ret = vdev->fops->ioctl(filp, cmd, arg);
-               mutex_unlock(&v4l2_ioctl_mutex);
+               if (cmd != VIDIOC_DQBUF)
+                       mutex_unlock(m);
        } else
                ret = -ENOTTY;
 
@@ -265,8 +290,8 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
 
        if (!vdev->fops->mmap)
                return ret;
-       if (vdev->lock)
-               mutex_lock(vdev->lock);
+       if (vdev->lock && mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->mmap(filp, vm);
        if (vdev->lock)
@@ -284,7 +309,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        mutex_lock(&videodev_lock);
        vdev = video_devdata(filp);
        /* return ENODEV if the video device has already been removed. */
-       if (vdev == NULL) {
+       if (vdev == NULL || !video_is_registered(vdev)) {
                mutex_unlock(&videodev_lock);
                return -ENODEV;
        }
@@ -292,8 +317,10 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        video_get(vdev);
        mutex_unlock(&videodev_lock);
        if (vdev->fops->open) {
-               if (vdev->lock)
-                       mutex_lock(vdev->lock);
+               if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
+                       ret = -ERESTARTSYS;
+                       goto err;
+               }
                if (video_is_registered(vdev))
                        ret = vdev->fops->open(filp);
                else
@@ -302,6 +329,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
                        mutex_unlock(vdev->lock);
        }
 
+err:
        /* decrease the refcount in case of an error */
        if (ret)
                video_put(vdev);
@@ -596,7 +624,12 @@ void video_unregister_device(struct video_device *vdev)
        if (!vdev || !video_is_registered(vdev))
                return;
 
+       mutex_lock(&videodev_lock);
+       /* This must be in a critical section to prevent a race with v4l2_open.
+        * Once this bit has been cleared video_get may never be called again.
+        */
        clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
+       mutex_unlock(&videodev_lock);
        device_unregister(&vdev->dev);
 }
 EXPORT_SYMBOL(video_unregister_device);
index 0b08f96b74a5ed5c750fdcc7541d2e38f069d79f..7fe6f92af480bc46288b3eff1d0358a30bd501e4 100644 (file)
@@ -35,6 +35,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
 
        INIT_LIST_HEAD(&v4l2_dev->subdevs);
        spin_lock_init(&v4l2_dev->lock);
+       mutex_init(&v4l2_dev->ioctl_lock);
        v4l2_dev->dev = dev;
        if (dev == NULL) {
                /* If dev == NULL, then name must be filled in by the caller */
index 635420d8d84a0536557582bbf507b4ae14f86f01..019ee206cbee0224fb71c9a86678c05ecf3da7d2 100644 (file)
@@ -815,7 +815,7 @@ out:
 
 static const struct v4l2_file_operations w9966_fops = {
        .owner          = THIS_MODULE,
-       .ioctl          = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
        .read           = w9966_v4l_read,
 };
 
index 135525649086401779ce84cfbb90d87b4c5a7131..fe8ef6419f831f36d52347ff275d8c96d4dc8c5f 100644 (file)
@@ -35,7 +35,6 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-ctrls.h>
-#include <media/wm8775.h>
 
 MODULE_DESCRIPTION("wm8775 driver");
 MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
@@ -51,16 +50,10 @@ enum {
        TOT_REGS
 };
 
-#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */
-#define ALC_EN 0x100  /* R17: ALC enable */
-
 struct wm8775_state {
        struct v4l2_subdev sd;
        struct v4l2_ctrl_handler hdl;
        struct v4l2_ctrl *mute;
-       struct v4l2_ctrl *vol;
-       struct v4l2_ctrl *bal;
-       struct v4l2_ctrl *loud;
        u8 input;               /* Last selected input (0-0xf) */
 };
 
@@ -92,30 +85,6 @@ static int wm8775_write(struct v4l2_subdev *sd, int reg, u16 val)
        return -1;
 }
 
-static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly)
-{
-       struct wm8775_state *state = to_state(sd);
-       u8 vol_l, vol_r;
-       int muted = 0 != state->mute->val;
-       u16 volume = (u16)state->vol->val;
-       u16 balance = (u16)state->bal->val;
-
-       /* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */
-       vol_l = (min(65536 - balance, 32768) * volume) >> 23;
-       vol_r = (min(balance, (u16)32768) * volume) >> 23;
-
-       /* Mute */
-       if (muted || quietly)
-               wm8775_write(sd, R21, 0x0c0 | state->input);
-
-       wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */
-       wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */
-
-       /* Un-mute */
-       if (!muted)
-               wm8775_write(sd, R21, state->input);
-}
-
 static int wm8775_s_routing(struct v4l2_subdev *sd,
                            u32 input, u32 output, u32 config)
 {
@@ -133,26 +102,25 @@ static int wm8775_s_routing(struct v4l2_subdev *sd,
        state->input = input;
        if (!v4l2_ctrl_g_ctrl(state->mute))
                return 0;
-       if (!v4l2_ctrl_g_ctrl(state->vol))
-               return 0;
-       if (!v4l2_ctrl_g_ctrl(state->bal))
-               return 0;
-       wm8775_set_audio(sd, 1);
+       wm8775_write(sd, R21, 0x0c0);
+       wm8775_write(sd, R14, 0x1d4);
+       wm8775_write(sd, R15, 0x1d4);
+       wm8775_write(sd, R21, 0x100 + state->input);
        return 0;
 }
 
 static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct v4l2_subdev *sd = to_sd(ctrl);
+       struct wm8775_state *state = to_state(sd);
 
        switch (ctrl->id) {
        case V4L2_CID_AUDIO_MUTE:
-       case V4L2_CID_AUDIO_VOLUME:
-       case V4L2_CID_AUDIO_BALANCE:
-               wm8775_set_audio(sd, 0);
-               return 0;
-       case V4L2_CID_AUDIO_LOUDNESS:
-               wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD);
+               wm8775_write(sd, R21, 0x0c0);
+               wm8775_write(sd, R14, 0x1d4);
+               wm8775_write(sd, R15, 0x1d4);
+               if (!ctrl->val)
+                       wm8775_write(sd, R21, 0x100 + state->input);
                return 0;
        }
        return -EINVAL;
@@ -176,7 +144,16 @@ static int wm8775_log_status(struct v4l2_subdev *sd)
 
 static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
 {
-       wm8775_set_audio(sd, 0);
+       struct wm8775_state *state = to_state(sd);
+
+       /* If I remove this, then it can happen that I have no
+          sound the first time I tune from static to a valid channel.
+          It's difficult to reproduce and is almost certainly related
+          to the zero cross detect circuit. */
+       wm8775_write(sd, R21, 0x0c0);
+       wm8775_write(sd, R14, 0x1d4);
+       wm8775_write(sd, R15, 0x1d4);
+       wm8775_write(sd, R21, 0x100 + state->input);
        return 0;
 }
 
@@ -226,7 +203,6 @@ static int wm8775_probe(struct i2c_client *client,
 {
        struct wm8775_state *state;
        struct v4l2_subdev *sd;
-       int err;
 
        /* Check if the adapter supports the needed features */
        if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -240,21 +216,15 @@ static int wm8775_probe(struct i2c_client *client,
                return -ENOMEM;
        sd = &state->sd;
        v4l2_i2c_subdev_init(sd, client, &wm8775_ops);
-       sd->grp_id = WM8775_GID; /* subdev group id */
        state->input = 2;
 
-       v4l2_ctrl_handler_init(&state->hdl, 4);
+       v4l2_ctrl_handler_init(&state->hdl, 1);
        state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
                        V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
-       state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
-                       V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/
-       state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
-                       V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768);
-       state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
-                       V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1);
        sd->ctrl_handler = &state->hdl;
-       err = state->hdl.error;
-       if (err) {
+       if (state->hdl.error) {
+               int err = state->hdl.error;
+
                v4l2_ctrl_handler_free(&state->hdl);
                kfree(state);
                return err;
@@ -266,25 +236,29 @@ static int wm8775_probe(struct i2c_client *client,
        wm8775_write(sd, R23, 0x000);
        /* Disable zero cross detect timeout */
        wm8775_write(sd, R7, 0x000);
-       /* HPF enable, I2S mode, 24-bit */
-       wm8775_write(sd, R11, 0x022);
+       /* Left justified, 24-bit mode */
+       wm8775_write(sd, R11, 0x021);
        /* Master mode, clock ratio 256fs */
        wm8775_write(sd, R12, 0x102);
        /* Powered up */
        wm8775_write(sd, R13, 0x000);
-       /* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */
-       wm8775_write(sd, R16, 0x1bb);
-       /* Set ALC mode and hold time */
-       wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD);
+       /* ADC gain +2.5dB, enable zero cross */
+       wm8775_write(sd, R14, 0x1d4);
+       /* ADC gain +2.5dB, enable zero cross */
+       wm8775_write(sd, R15, 0x1d4);
+       /* ALC Stereo, ALC target level -1dB FS max gain +8dB */
+       wm8775_write(sd, R16, 0x1bf);
+       /* Enable gain control, use zero cross detection,
+          ALC hold time 42.6 ms */
+       wm8775_write(sd, R17, 0x185);
        /* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */
        wm8775_write(sd, R18, 0x0a2);
        /* Enable noise gate, threshold -72dBfs */
        wm8775_write(sd, R19, 0x005);
-       /* Transient window 4ms, ALC min gain -5dB  */
-       wm8775_write(sd, R20, 0x0fb);
-
-       wm8775_set_audio(sd, 1);      /* set volume/mute/mux */
-
+       /* Transient window 4ms, lower PGA gain limit -1dB */
+       wm8775_write(sd, R20, 0x07a);
+       /* LRBOTH = 1, use input 2. */
+       wm8775_write(sd, R21, 0x102);
        return 0;
 }
 
index dbe1c93c1af3eeac287cc795f16307aa44f86ccc..d9640a623ff483446822e4370127c376d3c631c5 100644 (file)
@@ -303,7 +303,7 @@ static irqreturn_t ab8500_irq(int irq, void *dev)
                        continue;
 
                do {
-                       int bit = __ffs(status);
+                       int bit = __ffs(value);
                        int line = i * 8 + bit;
 
                        handle_nested_irq(ab8500->irq_base + line);
index 7d2563fc15c6096ba30a37f15eb4c95c3cfae68a..76cadcf3b1fee2ccf996d318c01137c53ba852a7 100644 (file)
@@ -1455,7 +1455,11 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                dev_err(wm831x->dev, "Failed to read parent ID: %d\n", ret);
                goto err;
        }
-       if (ret != 0x6204) {
+       switch (ret) {
+       case 0x6204:
+       case 0x6246:
+               break;
+       default:
                dev_err(wm831x->dev, "Device is not a WM831x: ID %x\n", ret);
                ret = -EINVAL;
                goto err;
@@ -1620,7 +1624,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        case WM8325:
                ret = mfd_add_devices(wm831x->dev, -1,
                                      wm8320_devs, ARRAY_SIZE(wm8320_devs),
-                                     NULL, 0);
+                                     NULL, wm831x->irq_base);
                break;
 
        default:
index 31ae07a36576678fb27dbd294623f6f8ac21cc9d..57dcf8fa774a7302be1fbb6f0104d6320c6287c8 100644 (file)
@@ -1773,6 +1773,7 @@ int mmc_pm_notify(struct notifier_block *notify_block,
 
        case PM_POST_SUSPEND:
        case PM_POST_HIBERNATION:
+       case PM_POST_RESTORE:
 
                spin_lock_irqsave(&host->lock, flags);
                host->rescan_disable = 0;
index 591ab540b407ad9805c3aa384795b2c59a7d8c69..d3e6a962f42343ac4f30fdd7dc7da8f13ff8a95a 100644 (file)
@@ -69,6 +69,7 @@
 #include <linux/highmem.h>
 
 #include <linux/mmc/host.h>
+#include <linux/mmc/sdio.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -493,10 +494,14 @@ static void at91_mci_send_command(struct at91mci_host *host, struct mmc_command
                else if (data->flags & MMC_DATA_WRITE)
                        cmdr |= AT91_MCI_TRCMD_START;
 
-               if (data->flags & MMC_DATA_STREAM)
-                       cmdr |= AT91_MCI_TRTYP_STREAM;
-               if (data->blocks > 1)
-                       cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+               if (cmd->opcode == SD_IO_RW_EXTENDED) {
+                       cmdr |= AT91_MCI_TRTYP_SDIO_BLOCK;
+               } else {
+                       if (data->flags & MMC_DATA_STREAM)
+                               cmdr |= AT91_MCI_TRTYP_STREAM;
+                       if (data->blocks > 1)
+                               cmdr |= AT91_MCI_TRTYP_MULTIPLE;
+               }
        }
        else {
                block_length = 0;
index 301351a5d83853f877953a1ecd10553ecc8f5c22..ad2a7a032cdf02478a80cd87055abce9648e31ca 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/stat.h>
 
 #include <linux/mmc/host.h>
+#include <linux/mmc/sdio.h>
 
 #include <mach/atmel-mci.h>
 #include <linux/atmel-mci.h>
@@ -532,12 +533,17 @@ static u32 atmci_prepare_command(struct mmc_host *mmc,
        data = cmd->data;
        if (data) {
                cmdr |= MCI_CMDR_START_XFER;
-               if (data->flags & MMC_DATA_STREAM)
-                       cmdr |= MCI_CMDR_STREAM;
-               else if (data->blocks > 1)
-                       cmdr |= MCI_CMDR_MULTI_BLOCK;
-               else
-                       cmdr |= MCI_CMDR_BLOCK;
+
+               if (cmd->opcode == SD_IO_RW_EXTENDED) {
+                       cmdr |= MCI_CMDR_SDIO_BLOCK;
+               } else {
+                       if (data->flags & MMC_DATA_STREAM)
+                               cmdr |= MCI_CMDR_STREAM;
+                       else if (data->blocks > 1)
+                               cmdr |= MCI_CMDR_MULTI_BLOCK;
+                       else
+                               cmdr |= MCI_CMDR_BLOCK;
+               }
 
                if (data->flags & MMC_DATA_READ)
                        cmdr |= MCI_CMDR_TRDIR_READ;
index 87b4fc6c98c2b32f4776e53f5eb0b3c8fdd6ad92..56302282566777daddc5c63bb2eff3582b0ba062 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/highmem.h>
 #include <linux/log2.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
 #include <linux/amba/bus.h>
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
@@ -45,6 +46,12 @@ static unsigned int fmax = 515633;
  *           is asserted (likewise for RX)
  * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
  *               is asserted (likewise for RX)
+ * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware
+ *             and will not work at all.
+ * @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when
+ *             using DMA.
+ * @sdio: variant supports SDIO
+ * @st_clkdiv: true if using a ST-specific clock divider algorithm
  */
 struct variant_data {
        unsigned int            clkreg;
@@ -52,6 +59,10 @@ struct variant_data {
        unsigned int            datalength_bits;
        unsigned int            fifosize;
        unsigned int            fifohalfsize;
+       bool                    broken_blockend;
+       bool                    broken_blockend_dma;
+       bool                    sdio;
+       bool                    st_clkdiv;
 };
 
 static struct variant_data variant_arm = {
@@ -65,6 +76,8 @@ static struct variant_data variant_u300 = {
        .fifohalfsize           = 8 * 4,
        .clkreg_enable          = 1 << 13, /* HWFCEN */
        .datalength_bits        = 16,
+       .broken_blockend_dma    = true,
+       .sdio                   = true,
 };
 
 static struct variant_data variant_ux500 = {
@@ -73,7 +86,11 @@ static struct variant_data variant_ux500 = {
        .clkreg                 = MCI_CLK_ENABLE,
        .clkreg_enable          = 1 << 14, /* HWFCEN */
        .datalength_bits        = 24,
+       .broken_blockend        = true,
+       .sdio                   = true,
+       .st_clkdiv              = true,
 };
+
 /*
  * This must be called with host->lock held
  */
@@ -86,7 +103,22 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
                if (desired >= host->mclk) {
                        clk = MCI_CLK_BYPASS;
                        host->cclk = host->mclk;
+               } else if (variant->st_clkdiv) {
+                       /*
+                        * DB8500 TRM says f = mclk / (clkdiv + 2)
+                        * => clkdiv = (mclk / f) - 2
+                        * Round the divider up so we don't exceed the max
+                        * frequency
+                        */
+                       clk = DIV_ROUND_UP(host->mclk, desired) - 2;
+                       if (clk >= 256)
+                               clk = 255;
+                       host->cclk = host->mclk / (clk + 2);
                } else {
+                       /*
+                        * PL180 TRM says f = mclk / (2 * (clkdiv + 1))
+                        * => clkdiv = mclk / (2 * f) - 1
+                        */
                        clk = host->mclk / (2 * desired) - 1;
                        if (clk >= 256)
                                clk = 255;
@@ -129,10 +161,26 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
        spin_lock(&host->lock);
 }
 
+static void mmci_set_mask1(struct mmci_host *host, unsigned int mask)
+{
+       void __iomem *base = host->base;
+
+       if (host->singleirq) {
+               unsigned int mask0 = readl(base + MMCIMASK0);
+
+               mask0 &= ~MCI_IRQ1MASK;
+               mask0 |= mask;
+
+               writel(mask0, base + MMCIMASK0);
+       }
+
+       writel(mask, base + MMCIMASK1);
+}
+
 static void mmci_stop_data(struct mmci_host *host)
 {
        writel(0, host->base + MMCIDATACTRL);
-       writel(0, host->base + MMCIMASK1);
+       mmci_set_mask1(host, 0);
        host->data = NULL;
 }
 
@@ -162,6 +210,8 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
        host->data = data;
        host->size = data->blksz * data->blocks;
        host->data_xfered = 0;
+       host->blockend = false;
+       host->dataend = false;
 
        mmci_init_sg(host, data);
 
@@ -196,9 +246,14 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
                irqmask = MCI_TXFIFOHALFEMPTYMASK;
        }
 
+       /* The ST Micro variants has a special bit to enable SDIO */
+       if (variant->sdio && host->mmc->card)
+               if (mmc_card_sdio(host->mmc->card))
+                       datactrl |= MCI_ST_DPSM_SDIOEN;
+
        writel(datactrl, base + MMCIDATACTRL);
        writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
-       writel(irqmask, base + MMCIMASK1);
+       mmci_set_mask1(host, irqmask);
 }
 
 static void
@@ -233,20 +288,9 @@ static void
 mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
              unsigned int status)
 {
-       if (status & MCI_DATABLOCKEND) {
-               host->data_xfered += data->blksz;
-#ifdef CONFIG_ARCH_U300
-               /*
-                * On the U300 some signal or other is
-                * badly routed so that a data write does
-                * not properly terminate with a MCI_DATAEND
-                * status flag. This quirk will make writes
-                * work again.
-                */
-               if (data->flags & MMC_DATA_WRITE)
-                       status |= MCI_DATAEND;
-#endif
-       }
+       struct variant_data *variant = host->variant;
+
+       /* First check for errors */
        if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
                dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
                if (status & MCI_DATACRCFAIL)
@@ -255,7 +299,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
                        data->error = -ETIMEDOUT;
                else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
                        data->error = -EIO;
-               status |= MCI_DATAEND;
+
+               /* Force-complete the transaction */
+               host->blockend = true;
+               host->dataend = true;
 
                /*
                 * We hit an error condition.  Ensure that any data
@@ -273,9 +320,64 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
                        local_irq_restore(flags);
                }
        }
-       if (status & MCI_DATAEND) {
+
+       /*
+        * On ARM variants in PIO mode, MCI_DATABLOCKEND
+        * is always sent first, and we increase the
+        * transfered number of bytes for that IRQ. Then
+        * MCI_DATAEND follows and we conclude the transaction.
+        *
+        * On the Ux500 single-IRQ variant MCI_DATABLOCKEND
+        * doesn't seem to immediately clear from the status,
+        * so we can't use it keep count when only one irq is
+        * used because the irq will hit for other reasons, and
+        * then the flag is still up. So we use the MCI_DATAEND
+        * IRQ at the end of the entire transfer because
+        * MCI_DATABLOCKEND is broken.
+        *
+        * In the U300, the IRQs can arrive out-of-order,
+        * e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND,
+        * so for this case we use the flags "blockend" and
+        * "dataend" to make sure both IRQs have arrived before
+        * concluding the transaction. (This does not apply
+        * to the Ux500 which doesn't fire MCI_DATABLOCKEND
+        * at all.) In DMA mode it suffers from the same problem
+        * as the Ux500.
+        */
+       if (status & MCI_DATABLOCKEND) {
+               /*
+                * Just being a little over-cautious, we do not
+                * use this progressive update if the hardware blockend
+                * flag is unreliable: since it can stay high between
+                * IRQs it will corrupt the transfer counter.
+                */
+               if (!variant->broken_blockend)
+                       host->data_xfered += data->blksz;
+               host->blockend = true;
+       }
+
+       if (status & MCI_DATAEND)
+               host->dataend = true;
+
+       /*
+        * On variants with broken blockend we shall only wait for dataend,
+        * on others we must sync with the blockend signal since they can
+        * appear out-of-order.
+        */
+       if (host->dataend && (host->blockend || variant->broken_blockend)) {
                mmci_stop_data(host);
 
+               /* Reset these flags */
+               host->blockend = false;
+               host->dataend = false;
+
+               /*
+                * Variants with broken blockend flags need to handle the
+                * end of the entire transfer here.
+                */
+               if (variant->broken_blockend && !data->error)
+                       host->data_xfered += data->blksz * data->blocks;
+
                if (!data->stop) {
                        mmci_request_end(host, data->mrq);
                } else {
@@ -356,7 +458,32 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem
                         variant->fifosize : variant->fifohalfsize;
                count = min(remain, maxcnt);
 
-               writesl(base + MMCIFIFO, ptr, count >> 2);
+               /*
+                * The ST Micro variant for SDIO transfer sizes
+                * less then 8 bytes should have clock H/W flow
+                * control disabled.
+                */
+               if (variant->sdio &&
+                   mmc_card_sdio(host->mmc->card)) {
+                       if (count < 8)
+                               writel(readl(host->base + MMCICLOCK) &
+                                       ~variant->clkreg_enable,
+                                       host->base + MMCICLOCK);
+                       else
+                               writel(readl(host->base + MMCICLOCK) |
+                                       variant->clkreg_enable,
+                                       host->base + MMCICLOCK);
+               }
+
+               /*
+                * SDIO especially may want to send something that is
+                * not divisible by 4 (as opposed to card sectors
+                * etc), and the FIFO only accept full 32-bit writes.
+                * So compensate by adding +3 on the count, a single
+                * byte become a 32bit write, 7 bytes will be two
+                * 32bit writes etc.
+                */
+               writesl(base + MMCIFIFO, ptr, (count + 3) >> 2);
 
                ptr += count;
                remain -= count;
@@ -437,7 +564,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
         * "any data available" mode.
         */
        if (status & MCI_RXACTIVE && host->size < variant->fifosize)
-               writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1);
+               mmci_set_mask1(host, MCI_RXDATAAVLBLMASK);
 
        /*
         * If we run out of data, disable the data IRQs; this
@@ -446,7 +573,7 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id)
         * stops us racing with our data end IRQ.
         */
        if (host->size == 0) {
-               writel(0, base + MMCIMASK1);
+               mmci_set_mask1(host, 0);
                writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
        }
 
@@ -469,6 +596,14 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
                struct mmc_data *data;
 
                status = readl(host->base + MMCISTATUS);
+
+               if (host->singleirq) {
+                       if (status & readl(host->base + MMCIMASK1))
+                               mmci_pio_irq(irq, dev_id);
+
+                       status &= ~MCI_IRQ1MASK;
+               }
+
                status &= readl(host->base + MMCIMASK0);
                writel(status, host->base + MMCICLEAR);
 
@@ -635,6 +770,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
        struct variant_data *variant = id->data;
        struct mmci_host *host;
        struct mmc_host *mmc;
+       unsigned int mask;
        int ret;
 
        /* must have platform data */
@@ -806,20 +942,30 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
        if (ret)
                goto unmap;
 
-       ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host);
-       if (ret)
-               goto irq0_free;
+       if (dev->irq[1] == NO_IRQ)
+               host->singleirq = true;
+       else {
+               ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED,
+                                 DRIVER_NAME " (pio)", host);
+               if (ret)
+                       goto irq0_free;
+       }
 
-       writel(MCI_IRQENABLE, host->base + MMCIMASK0);
+       mask = MCI_IRQENABLE;
+       /* Don't use the datablockend flag if it's broken */
+       if (variant->broken_blockend)
+               mask &= ~MCI_DATABLOCKEND;
 
-       amba_set_drvdata(dev, mmc);
+       writel(mask, host->base + MMCIMASK0);
 
-       mmc_add_host(mmc);
+       amba_set_drvdata(dev, mmc);
 
-       dev_info(&dev->dev, "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n",
-               mmc_hostname(mmc), amba_rev(dev), amba_config(dev),
+       dev_info(&dev->dev, "%s: PL%03x rev%u at 0x%08llx irq %d,%d\n",
+               mmc_hostname(mmc), amba_part(dev), amba_rev(dev),
                (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]);
 
+       mmc_add_host(mmc);
+
        return 0;
 
  irq0_free:
@@ -864,7 +1010,8 @@ static int __devexit mmci_remove(struct amba_device *dev)
                writel(0, host->base + MMCIDATACTRL);
 
                free_irq(dev->irq[0], host);
-               free_irq(dev->irq[1], host);
+               if (!host->singleirq)
+                       free_irq(dev->irq[1], host);
 
                if (host->gpio_wp != -ENOSYS)
                        gpio_free(host->gpio_wp);
index 4ae887fc01892e3a844b064ce6dd72c3a8773aa9..df06f01aac8953a482bb25fdf3261f2496b6504c 100644 (file)
        MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK|       \
        MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
 
+/* These interrupts are directed to IRQ1 when two IRQ lines are available */
+#define MCI_IRQ1MASK \
+       (MCI_RXFIFOHALFFULLMASK | MCI_RXDATAAVLBLMASK | \
+        MCI_TXFIFOHALFEMPTYMASK)
+
 #define NR_SG          16
 
 struct clk;
@@ -154,6 +159,7 @@ struct mmci_host {
        int                     gpio_cd;
        int                     gpio_wp;
        int                     gpio_cd_irq;
+       bool                    singleirq;
 
        unsigned int            data_xfered;
 
@@ -171,6 +177,9 @@ struct mmci_host {
        struct timer_list       timer;
        unsigned int            oldstat;
 
+       bool                    blockend;
+       bool                    dataend;
+
        /* pio stuff */
        struct sg_mapping_iter  sg_miter;
        unsigned int            size;
index 09b099bfab2b1b75c5dc7e3f0b323393e0124f8a..bdf11d89a4997887fc1c1145b393ef91ad5785a4 100644 (file)
@@ -702,6 +702,7 @@ static int __devinit atl1c_sw_init(struct atl1c_adapter *adapter)
 
 
        adapter->wol = 0;
+       device_set_wakeup_enable(&pdev->dev, false);
        adapter->link_speed = SPEED_0;
        adapter->link_duplex = FULL_DUPLEX;
        adapter->num_rx_queues = AT_DEF_RECEIVE_QUEUE;
@@ -2444,8 +2445,9 @@ static int atl1c_close(struct net_device *netdev)
        return 0;
 }
 
-static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
+static int atl1c_suspend(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct atl1c_adapter *adapter = netdev_priv(netdev);
        struct atl1c_hw *hw = &adapter->hw;
@@ -2454,7 +2456,6 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
        u32 wol_ctrl_data = 0;
        u16 mii_intr_status_data = 0;
        u32 wufc = adapter->wol;
-       int retval = 0;
 
        atl1c_disable_l0s_l1(hw);
        if (netif_running(netdev)) {
@@ -2462,9 +2463,6 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
                atl1c_down(adapter);
        }
        netif_device_detach(netdev);
-       retval = pci_save_state(pdev);
-       if (retval)
-               return retval;
 
        if (wufc)
                if (atl1c_phy_power_saving(hw) != 0)
@@ -2525,12 +2523,8 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
                AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data);
                AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
 
-               /* pcie patch */
-               device_set_wakeup_enable(&pdev->dev, 1);
-
                AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
                        GPHY_CTRL_EXT_RESET);
-               pci_prepare_to_sleep(pdev);
        } else {
                AT_WRITE_REG(hw, REG_GPHY_CTRL, GPHY_CTRL_POWER_SAVING);
                master_ctrl_data |= MASTER_CTRL_CLK_SEL_DIS;
@@ -2540,25 +2534,17 @@ static int atl1c_suspend(struct pci_dev *pdev, pm_message_t state)
                AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data);
                AT_WRITE_REG(hw, REG_WOL_CTRL, 0);
                hw->phy_configured = false; /* re-init PHY when resume */
-               pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
        }
 
-       pci_disable_device(pdev);
-       pci_set_power_state(pdev, pci_choose_state(pdev, state));
-
        return 0;
 }
 
-static int atl1c_resume(struct pci_dev *pdev)
+static int atl1c_resume(struct device *dev)
 {
+       struct pci_dev *pdev = to_pci_dev(dev);
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct atl1c_adapter *adapter = netdev_priv(netdev);
 
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       pci_enable_wake(pdev, PCI_D3hot, 0);
-       pci_enable_wake(pdev, PCI_D3cold, 0);
-
        AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0);
        atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE |
                        ATL1C_PCIE_PHY_RESET);
@@ -2582,7 +2568,12 @@ static int atl1c_resume(struct pci_dev *pdev)
 
 static void atl1c_shutdown(struct pci_dev *pdev)
 {
-       atl1c_suspend(pdev, PMSG_SUSPEND);
+       struct net_device *netdev = pci_get_drvdata(pdev);
+       struct atl1c_adapter *adapter = netdev_priv(netdev);
+
+       atl1c_suspend(&pdev->dev);
+       pci_wake_from_d3(pdev, adapter->wol);
+       pci_set_power_state(pdev, PCI_D3hot);
 }
 
 static const struct net_device_ops atl1c_netdev_ops = {
@@ -2886,16 +2877,16 @@ static struct pci_error_handlers atl1c_err_handler = {
        .resume = atl1c_io_resume,
 };
 
+static SIMPLE_DEV_PM_OPS(atl1c_pm_ops, atl1c_suspend, atl1c_resume);
+
 static struct pci_driver atl1c_driver = {
        .name     = atl1c_driver_name,
        .id_table = atl1c_pci_tbl,
        .probe    = atl1c_probe,
        .remove   = __devexit_p(atl1c_remove),
-       /* Power Managment Hooks */
-       .suspend  = atl1c_suspend,
-       .resume   = atl1c_resume,
        .shutdown = atl1c_shutdown,
-       .err_handler = &atl1c_err_handler
+       .err_handler = &atl1c_err_handler,
+       .driver.pm = &atl1c_pm_ops,
 };
 
 /*
index 53363108994ee93bed670940b0eb91170a389456..3acf5123a6efa8c0e21d76b7deb487a76d21ea3e 100644 (file)
@@ -3504,6 +3504,8 @@ static int atl1_set_ringparam(struct net_device *netdev,
        struct atl1_rfd_ring rfd_old, rfd_new;
        struct atl1_rrd_ring rrd_old, rrd_new;
        struct atl1_ring_header rhdr_old, rhdr_new;
+       struct atl1_smb smb;
+       struct atl1_cmb cmb;
        int err;
 
        tpd_old = adapter->tpd_ring;
@@ -3544,11 +3546,19 @@ static int atl1_set_ringparam(struct net_device *netdev,
                adapter->rrd_ring = rrd_old;
                adapter->tpd_ring = tpd_old;
                adapter->ring_header = rhdr_old;
+               /*
+                * Save SMB and CMB, since atl1_free_ring_resources
+                * will clear them.
+                */
+               smb = adapter->smb;
+               cmb = adapter->cmb;
                atl1_free_ring_resources(adapter);
                adapter->rfd_ring = rfd_new;
                adapter->rrd_ring = rrd_new;
                adapter->tpd_ring = tpd_new;
                adapter->ring_header = rhdr_new;
+               adapter->smb = smb;
+               adapter->cmb = cmb;
 
                err = atl1_up(adapter);
                if (err)
index 4594a28b1f665ef7923aa462739b96e39182ac5e..d64313b7090e2217038130bb314cedde2bb7c152 100644 (file)
@@ -234,7 +234,7 @@ struct be_adapter {
        u8 __iomem *db;         /* Door Bell */
        u8 __iomem *pcicfg;     /* PCI config space */
 
-       spinlock_t mbox_lock;   /* For serializing mbox cmds to BE card */
+       struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
        struct be_dma_mem mbox_mem;
        /* Mbox mem is adjusted to align to 16 bytes. The allocated addr
         * is stored for freeing purpose */
index e4465d222a7d019654c27c5f4d3db89067f89cf8..1c8c79c9d214e45feb59dbf20b439be1d369702a 100644 (file)
@@ -462,7 +462,8 @@ int be_cmd_fw_init(struct be_adapter *adapter)
        u8 *wrb;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = (u8 *)wrb_from_mbox(adapter);
        *wrb++ = 0xFF;
@@ -476,7 +477,7 @@ int be_cmd_fw_init(struct be_adapter *adapter)
 
        status = be_mbox_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 
@@ -491,7 +492,8 @@ int be_cmd_fw_clean(struct be_adapter *adapter)
        if (adapter->eeh_err)
                return -EIO;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = (u8 *)wrb_from_mbox(adapter);
        *wrb++ = 0xFF;
@@ -505,7 +507,7 @@ int be_cmd_fw_clean(struct be_adapter *adapter)
 
        status = be_mbox_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 int be_cmd_eq_create(struct be_adapter *adapter,
@@ -516,7 +518,8 @@ int be_cmd_eq_create(struct be_adapter *adapter,
        struct be_dma_mem *q_mem = &eq->dma_mem;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -546,7 +549,7 @@ int be_cmd_eq_create(struct be_adapter *adapter,
                eq->created = true;
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 
@@ -558,7 +561,8 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
        struct be_cmd_req_mac_query *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -583,7 +587,7 @@ int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
                memcpy(mac_addr, resp->mac.addr, ETH_ALEN);
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 
@@ -667,7 +671,8 @@ int be_cmd_cq_create(struct be_adapter *adapter,
        void *ctxt;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -701,7 +706,7 @@ int be_cmd_cq_create(struct be_adapter *adapter,
                cq->created = true;
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
 
        return status;
 }
@@ -724,7 +729,8 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
        void *ctxt;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -754,7 +760,7 @@ int be_cmd_mccq_create(struct be_adapter *adapter,
                mccq->id = le16_to_cpu(resp->id);
                mccq->created = true;
        }
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
 
        return status;
 }
@@ -769,7 +775,8 @@ int be_cmd_txq_create(struct be_adapter *adapter,
        void *ctxt;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -801,7 +808,7 @@ int be_cmd_txq_create(struct be_adapter *adapter,
                txq->created = true;
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
 
        return status;
 }
@@ -816,7 +823,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
        struct be_dma_mem *q_mem = &rxq->dma_mem;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -843,7 +851,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter,
                *rss_id = resp->rss_id;
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
 
        return status;
 }
@@ -862,7 +870,8 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
        if (adapter->eeh_err)
                return -EIO;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -899,7 +908,7 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
 
        status = be_mbox_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
 
        return status;
 }
@@ -915,7 +924,8 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
        struct be_cmd_req_if_create *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -941,7 +951,7 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
                        *pmac_id = le32_to_cpu(resp->pmac_id);
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 
@@ -955,7 +965,8 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
        if (adapter->eeh_err)
                return -EIO;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -970,7 +981,7 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
 
        status = be_mbox_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
 
        return status;
 }
@@ -1060,7 +1071,8 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
        struct be_cmd_req_get_fw_version *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -1077,7 +1089,7 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
                strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN);
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 
@@ -1322,7 +1334,8 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
        struct be_cmd_req_query_fw_cfg *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -1341,7 +1354,7 @@ int be_cmd_query_fw_cfg(struct be_adapter *adapter, u32 *port_num,
                *caps = le32_to_cpu(resp->function_caps);
        }
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 
@@ -1352,7 +1365,8 @@ int be_cmd_reset_function(struct be_adapter *adapter)
        struct be_cmd_req_hdr *req;
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -1365,7 +1379,7 @@ int be_cmd_reset_function(struct be_adapter *adapter)
 
        status = be_mbox_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 
@@ -1376,7 +1390,8 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
        u32 myhash[10];
        int status;
 
-       spin_lock(&adapter->mbox_lock);
+       if (mutex_lock_interruptible(&adapter->mbox_lock))
+               return -1;
 
        wrb = wrb_from_mbox(adapter);
        req = embedded_payload(wrb);
@@ -1396,7 +1411,7 @@ int be_cmd_rss_config(struct be_adapter *adapter, u8 *rsstable, u16 table_size)
 
        status = be_mbox_notify_wait(adapter);
 
-       spin_unlock(&adapter->mbox_lock);
+       mutex_unlock(&adapter->mbox_lock);
        return status;
 }
 
index 93354eee2cfd1e679929054c9cc28fe7b35dea51..fd251b59b7f96b4d58ca0f7b22e91e22485d7005 100644 (file)
@@ -2677,7 +2677,7 @@ static int be_ctrl_init(struct be_adapter *adapter)
        }
        memset(mc_cmd_mem->va, 0, mc_cmd_mem->size);
 
-       spin_lock_init(&adapter->mbox_lock);
+       mutex_init(&adapter->mbox_lock);
        spin_lock_init(&adapter->mcc_lock);
        spin_lock_init(&adapter->mcc_cq_lock);
 
index 121b073a6c3fae1985c164071f0a8f285dba0c14..84fbd4ebd778d472a9cf115cfc4faaf72e92939e 100644 (file)
@@ -88,7 +88,12 @@ static void bond_na_send(struct net_device *slave_dev,
        }
 
        if (vlan_id) {
-               skb = vlan_put_tag(skb, vlan_id);
+               /* The Ethernet header is not present yet, so it is
+                * too early to insert a VLAN tag.  Force use of an
+                * out-of-line tag here and let dev_hard_start_xmit()
+                * insert it if the slave hardware can't.
+                */
+               skb = __vlan_hwaccel_put_tag(skb, vlan_id);
                if (!skb) {
                        pr_err("failed to insert VLAN tag\n");
                        return;
index d0ea760ce419f0ae8040bf880cd80013c651a93a..3b16c34ed86e93ddfacd0338ef42f687ab70fce7 100644 (file)
@@ -418,36 +418,11 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
  * @bond: bond device that got this skb for tx.
  * @skb: hw accel VLAN tagged skb to transmit
  * @slave_dev: slave that is supposed to xmit this skbuff
- *
- * When the bond gets an skb to transmit that is
- * already hardware accelerated VLAN tagged, and it
- * needs to relay this skb to a slave that is not
- * hw accel capable, the skb needs to be "unaccelerated",
- * i.e. strip the hwaccel tag and re-insert it as part
- * of the payload.
  */
 int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
                        struct net_device *slave_dev)
 {
-       unsigned short uninitialized_var(vlan_id);
-
-       /* Test vlan_list not vlgrp to catch and handle 802.1p tags */
-       if (!list_empty(&bond->vlan_list) &&
-           !(slave_dev->features & NETIF_F_HW_VLAN_TX) &&
-           vlan_get_tag(skb, &vlan_id) == 0) {
-               skb->dev = slave_dev;
-               skb = vlan_put_tag(skb, vlan_id);
-               if (!skb) {
-                       /* vlan_put_tag() frees the skb in case of error,
-                        * so return success here so the calling functions
-                        * won't attempt to free is again.
-                        */
-                       return 0;
-               }
-       } else {
-               skb->dev = slave_dev;
-       }
-
+       skb->dev = slave_dev;
        skb->priority = 1;
 #ifdef CONFIG_NET_POLL_CONTROLLER
        if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) {
@@ -1203,11 +1178,13 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
                                bond_do_fail_over_mac(bond, new_active,
                                                      old_active);
 
-                       bond->send_grat_arp = bond->params.num_grat_arp;
-                       bond_send_gratuitous_arp(bond);
+                       if (netif_running(bond->dev)) {
+                               bond->send_grat_arp = bond->params.num_grat_arp;
+                               bond_send_gratuitous_arp(bond);
 
-                       bond->send_unsol_na = bond->params.num_unsol_na;
-                       bond_send_unsolicited_na(bond);
+                               bond->send_unsol_na = bond->params.num_unsol_na;
+                               bond_send_unsolicited_na(bond);
+                       }
 
                        write_unlock_bh(&bond->curr_slave_lock);
                        read_unlock(&bond->lock);
@@ -1221,8 +1198,9 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
 
        /* resend IGMP joins since active slave has changed or
         * all were sent on curr_active_slave */
-       if ((USES_PRIMARY(bond->params.mode) && new_active) ||
-           bond->params.mode == BOND_MODE_ROUNDROBIN) {
+       if (((USES_PRIMARY(bond->params.mode) && new_active) ||
+            bond->params.mode == BOND_MODE_ROUNDROBIN) &&
+           netif_running(bond->dev)) {
                bond->igmp_retrans = bond->params.resend_igmp;
                queue_delayed_work(bond->wq, &bond->mcast_work, 0);
        }
index c2f081352a037894d6e8238ccb70c39e796c4a69..4feeb2d650a4f478bc6ab4f3c70db3f3563c622d 100644 (file)
@@ -269,11 +269,11 @@ static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct n
 
        bond_for_each_slave(bond, slave, i) {
                if (slave->dev == slave_dev) {
-                       break;
+                       return slave;
                }
        }
 
-       return slave;
+       return 0;
 }
 
 static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
index 92bac19ad60ab0be5383b7566f48cc5dbbf2ab8e..6dff32196c92bcb65d10bda3c54cbb0048dee416 100644 (file)
@@ -940,7 +940,7 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
                                           &udev->l2_ring_map,
                                           GFP_KERNEL | __GFP_COMP);
        if (!udev->l2_ring)
-               return -ENOMEM;
+               goto err_udev;
 
        udev->l2_buf_size = (cp->l2_rx_ring_size + 1) * cp->l2_single_buf_size;
        udev->l2_buf_size = PAGE_ALIGN(udev->l2_buf_size);
@@ -948,7 +948,7 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
                                          &udev->l2_buf_map,
                                          GFP_KERNEL | __GFP_COMP);
        if (!udev->l2_buf)
-               return -ENOMEM;
+               goto err_dma;
 
        write_lock(&cnic_dev_lock);
        list_add(&udev->list, &cnic_udev_list);
@@ -959,6 +959,12 @@ static int cnic_alloc_uio_rings(struct cnic_dev *dev, int pages)
        cp->udev = udev;
 
        return 0;
+ err_dma:
+       dma_free_coherent(&udev->pdev->dev, udev->l2_ring_size,
+                         udev->l2_ring, udev->l2_ring_map);
+ err_udev:
+       kfree(udev);
+       return -ENOMEM;
 }
 
 static int cnic_init_uio(struct cnic_dev *dev)
index 1f37ee6b2a2626282fd5a772cc21f821321b9379..d6cf502906cfeeafa41b1072a9aadf8a97a5b475 100644 (file)
@@ -263,6 +263,13 @@ static void ehea_get_ethtool_stats(struct net_device *dev,
 
 static int ehea_set_flags(struct net_device *dev, u32 data)
 {
+       /* Avoid changing the VLAN flags */
+       if ((data & (ETH_FLAG_RXVLAN | ETH_FLAG_TXVLAN)) !=
+           (ethtool_op_get_flags(dev) & (ETH_FLAG_RXVLAN |
+                                         ETH_FLAG_TXVLAN))){
+               return -EINVAL;
+       }
+
        return ethtool_op_set_flags(dev, data, ETH_FLAG_LRO
                                        | ETH_FLAG_TXVLAN
                                        | ETH_FLAG_RXVLAN);
index aa56963ad55820e2a763d64c102a36ae1b35dabf..c353bf3113cc335088e4322703a91cd5add4d60d 100644 (file)
@@ -935,7 +935,7 @@ static void epic_init_ring(struct net_device *dev)
 
        /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        for (i = 0; i < RX_RING_SIZE; i++) {
-               struct sk_buff *skb = dev_alloc_skb(ep->rx_buf_sz);
+               struct sk_buff *skb = dev_alloc_skb(ep->rx_buf_sz + 2);
                ep->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
@@ -1233,7 +1233,7 @@ static int epic_rx(struct net_device *dev, int budget)
                entry = ep->dirty_rx % RX_RING_SIZE;
                if (ep->rx_skbuff[entry] == NULL) {
                        struct sk_buff *skb;
-                       skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz);
+                       skb = ep->rx_skbuff[entry] = dev_alloc_skb(ep->rx_buf_sz + 2);
                        if (skb == NULL)
                                break;
                        skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
index 9a6485892b3d48dfbcf783a27b670be83704e803..80d25ed533447735d55804e152bb8d581fc911ef 100644 (file)
@@ -1202,7 +1202,7 @@ static void hamachi_init_ring(struct net_device *dev)
        }
        /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        for (i = 0; i < RX_RING_SIZE; i++) {
-               struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz);
+               struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz + 2);
                hmp->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
@@ -1669,7 +1669,7 @@ static int hamachi_rx(struct net_device *dev)
                entry = hmp->dirty_rx % RX_RING_SIZE;
                desc = &(hmp->rx_ring[entry]);
                if (hmp->rx_skbuff[entry] == NULL) {
-                       struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz);
+                       struct sk_buff *skb = dev_alloc_skb(hmp->rx_buf_sz + 2);
 
                        hmp->rx_skbuff[entry] = skb;
                        if (skb == NULL)
index 8a4d19e5de064bd3fbbb11a2d2e916a28cf593b0..f1047dd8a526715857929e8ca86a47d846e5a15e 100644 (file)
@@ -690,6 +690,7 @@ static void block_output(struct net_device *dev, int count,
 static struct pcmcia_device_id axnet_ids[] = {
        PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x016c, 0x0081),
        PCMCIA_DEVICE_MANF_CARD(0x018a, 0x0301),
+       PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),
        PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0301),
        PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0303),
        PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0309),
index d05c44692f08306f4dc04dbbb30098c46fd8e362..2c158910f7ea8f1784f629df23bfee2a21cc41c9 100644 (file)
@@ -1493,7 +1493,6 @@ static struct pcmcia_device_id pcnet_ids[] = {
        PCMCIA_DEVICE_MANF_CARD(0x0149, 0x4530),
        PCMCIA_DEVICE_MANF_CARD(0x0149, 0xc1ab),
        PCMCIA_DEVICE_MANF_CARD(0x0186, 0x0110),
-       PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x2328),
        PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x8041),
        PCMCIA_DEVICE_MANF_CARD(0x0213, 0x2452),
        PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0300),
index 39659976a1acfb1589834368aab20080c894d6eb..89294b43c4a901f8ce927e1981ad317b95538f44 100644 (file)
@@ -1285,6 +1285,11 @@ ppp_push(struct ppp *ppp)
 }
 
 #ifdef CONFIG_PPP_MULTILINK
+static bool mp_protocol_compress __read_mostly = true;
+module_param(mp_protocol_compress, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(mp_protocol_compress,
+                "compress protocol id in multilink fragments");
+
 /*
  * Divide a packet to be transmitted into fragments and
  * send them out the individual links.
@@ -1347,10 +1352,10 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
        if (nfree == 0 || nfree < navail / 2)
                return 0; /* can't take now, leave it in xmit_pending */
 
-       /* Do protocol field compression (XXX this should be optional) */
+       /* Do protocol field compression */
        p = skb->data;
        len = skb->len;
-       if (*p == 0) {
+       if (*p == 0 && mp_protocol_compress) {
                ++p;
                --len;
        }
index 0a66fed52e8ed48e9a82bfdcfb831957acc491cf..16c62659cdd96040e7831d0e7d7e18bc58832752 100644 (file)
@@ -412,7 +412,7 @@ static  int skfp_driver_init(struct net_device *dev)
                bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev,
                                                         bp->SharedMemSize,
                                                         &bp->SharedMemDMA);
-               if (!bp->SharedMemSize) {
+               if (!bp->SharedMemAddr) {
                        printk("could not allocate mem for ");
                        printk("hardware module: %ld byte\n",
                               bp->SharedMemSize);
index 4adf124227877e704fe66a7bb74919738bbd46c5..a4f2bd52e546f522995df2fb7fae5721f94e0244 100644 (file)
@@ -148,7 +148,7 @@ static int full_duplex[MAX_UNITS] = {0, };
  * This SUCKS.
  * We need a much better method to determine if dma_addr_t is 64-bit.
  */
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || (defined(CONFIG_MIPS) && ((defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || defined(CONFIG_64BIT))) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))
 /* 64-bit dma_addr_t */
 #define ADDR_64BITS    /* This chip uses 64 bit addresses. */
 #define netdrv_addr_t __le64
index 3ed2a67bd6d36c5da4608570bc8d494faa614f59..b409d7ec4ac15ff5e5eb82c2aff17111d48954a3 100644 (file)
@@ -1016,7 +1016,7 @@ static void init_ring(struct net_device *dev)
 
        /* Fill in the Rx buffers.  Handle allocation failure gracefully. */
        for (i = 0; i < RX_RING_SIZE; i++) {
-               struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
+               struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz + 2);
                np->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
@@ -1407,7 +1407,7 @@ static void refill_rx (struct net_device *dev)
                struct sk_buff *skb;
                entry = np->dirty_rx % RX_RING_SIZE;
                if (np->rx_skbuff[entry] == NULL) {
-                       skb = dev_alloc_skb(np->rx_buf_sz);
+                       skb = dev_alloc_skb(np->rx_buf_sz + 2);
                        np->rx_skbuff[entry] = skb;
                        if (skb == NULL)
                                break;          /* Better luck next round. */
index 8b3dc1eb401541e8e1c3de31ce5308d84f477845..296000bf5a25d9186826da3c3c2f401802409e07 100644 (file)
@@ -324,7 +324,7 @@ static int bdx_fw_load(struct bdx_priv *priv)
        ENTER;
        master = READ_REG(priv, regINIT_SEMAPHORE);
        if (!READ_REG(priv, regINIT_STATUS) && master) {
-               rc = request_firmware(&fw, "tehuti/firmware.bin", &priv->pdev->dev);
+               rc = request_firmware(&fw, "tehuti/bdx.bin", &priv->pdev->dev);
                if (rc)
                        goto out;
                bdx_tx_push_desc_safe(priv, (char *)fw->data, fw->size);
@@ -2510,4 +2510,4 @@ module_exit(bdx_module_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(BDX_DRV_DESC);
-MODULE_FIRMWARE("tehuti/firmware.bin");
+MODULE_FIRMWARE("tehuti/bdx.bin");
index 30ccbb6d097af220dced34f430723a3b3c5a9dca..6f97b7bbcbf13a29b9f2c567eb317a12ec51609c 100644 (file)
@@ -12658,7 +12658,7 @@ static void __devinit tg3_read_vpd(struct tg3 *tp)
                        cnt = pci_read_vpd(tp->pdev, pos,
                                           TG3_NVM_VPD_LEN - pos,
                                           &vpd_data[pos]);
-                       if (cnt == -ETIMEDOUT || -EINTR)
+                       if (cnt == -ETIMEDOUT || cnt == -EINTR)
                                cnt = 0;
                        else if (cnt < 0)
                                goto out_not_found;
index 5b83c3f35f47c3421a518aaa04fb39224dac2ed3..a3c46f6a15e7c5b02a91542406208928cdb23a6d 100644 (file)
@@ -1004,7 +1004,6 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
        }
 
        strcpy(info->driver, KBUILD_MODNAME);
-       strcpy(info->version, UTS_RELEASE);
        strcpy(info->bus_info, pci_name(pci_dev));
 }
 
index aea4645be7f68956472e6f6fbefeadb2e049f060..6140b56cce53d2205638803ce13702bcbfeb8910 100644 (file)
@@ -1507,6 +1507,10 @@ static const struct usb_device_id        products [] = {
        // ASIX AX88178 10/100/1000
        USB_DEVICE (0x0b95, 0x1780),
        .driver_info = (unsigned long) &ax88178_info,
+}, {
+       // Logitec LAN-GTJ/U2A
+       USB_DEVICE (0x0789, 0x0160),
+       .driver_info = (unsigned long) &ax88178_info,
 }, {
        // Linksys USB200M Rev 2
        USB_DEVICE (0x13b1, 0x0018),
index a6281e3987b5c47d6a061e1bb45538000bd6745e..2b791392e788ef893657d04056df673fc3ded672 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * MOSCHIP MCS7830 based USB 2.0 Ethernet Devices
+ * MOSCHIP MCS7830 based (7730/7830/7832) USB 2.0 Ethernet Devices
  *
  * based on usbnet.c, asix.c and the vendor provided mcs7830 driver
  *
@@ -11,6 +11,9 @@
  *
  * Definitions gathered from MOSCHIP, Data Sheet_7830DA.pdf (thanks!).
  *
+ * 2010-12-19: add 7832 USB PID ("functionality same as MCS7830"),
+ *             per active notification by manufacturer
+ *
  * TODO:
  * - support HIF_REG_CONFIG_SLEEPMODE/HIF_REG_CONFIG_TXENABLE (via autopm?)
  * - implement ethtool_ops get_pauseparam/set_pauseparam
@@ -60,6 +63,7 @@
 #define MCS7830_MAX_MCAST      64
 
 #define MCS7830_VENDOR_ID      0x9710
+#define MCS7832_PRODUCT_ID     0x7832
 #define MCS7830_PRODUCT_ID     0x7830
 #define MCS7730_PRODUCT_ID     0x7730
 
@@ -351,7 +355,7 @@ static int mcs7830_set_autoneg(struct usbnet *dev, int ptrUserPhyMode)
        if (!ret)
                ret = mcs7830_write_phy(dev, MII_BMCR,
                                BMCR_ANENABLE | BMCR_ANRESTART  );
-       return ret < 0 ? : 0;
+       return ret;
 }
 
 
@@ -626,7 +630,7 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 }
 
 static const struct driver_info moschip_info = {
-       .description    = "MOSCHIP 7830/7730 usb-NET adapter",
+       .description    = "MOSCHIP 7830/7832/7730 usb-NET adapter",
        .bind           = mcs7830_bind,
        .rx_fixup       = mcs7830_rx_fixup,
        .flags          = FLAG_ETHER,
@@ -644,6 +648,10 @@ static const struct driver_info sitecom_info = {
 };
 
 static const struct usb_device_id products[] = {
+       {
+               USB_DEVICE(MCS7830_VENDOR_ID, MCS7832_PRODUCT_ID),
+               .driver_info = (unsigned long) &moschip_info,
+       },
        {
                USB_DEVICE(MCS7830_VENDOR_ID, MCS7830_PRODUCT_ID),
                .driver_info = (unsigned long) &moschip_info,
index 0bbc0c3231358de20f395d9fd34b05279e0e13fd..cc83fa71c3ffb970b5107aa812e1e1956c9c7c82 100644 (file)
@@ -166,7 +166,9 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
        if (!(rcv->flags & IFF_UP))
                goto tx_drop;
 
-       if (dev->features & NETIF_F_NO_CSUM)
+       /* don't change ip_summed == CHECKSUM_PARTIAL, as that
+          will cause bad checksum on forwarded packets */
+       if (skb->ip_summed == CHECKSUM_NONE)
                skb->ip_summed = rcv_priv->ip_summed;
 
        length = skb->len + ETH_HLEN;
index 25a2722c8a986ce35a8a37a9076814095cc70ee3..1d9aed6457234fe0cc18c34fe198dc6ca4e4d62b 100644 (file)
@@ -891,7 +891,6 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
 
        SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops);
 
-       netif_stop_queue(dev);
 }
 
 static int hostap_enable_hostapd(local_info_t *local, int rtnl_locked)
index db540910b1104d42b5d20d15e542c3fc5da7649c..0e027f787fbce6452b0c78fefc24dbd30cb75100 100644 (file)
@@ -315,6 +315,7 @@ struct iwl_cfg iwl100_bgn_cfg = {
        .mod_params = &iwlagn_mod_params,
        .base_params = &iwl1000_base_params,
        .ht_params = &iwl1000_ht_params,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl100_bg_cfg = {
@@ -330,6 +331,7 @@ struct iwl_cfg iwl100_bg_cfg = {
        .ops = &iwl1000_ops,
        .mod_params = &iwlagn_mod_params,
        .base_params = &iwl1000_base_params,
+       .use_new_eeprom_reading = true,
 };
 
 MODULE_FIRMWARE(IWL1000_MODULE_FIRMWARE(IWL1000_UCODE_API_MAX));
index 11e6532fc573d1ed93d5ec4aaf886342d0fe8073..0ceeaac85eda1ab8a8dd8a046044b47dc5e5df63 100644 (file)
@@ -561,6 +561,7 @@ struct iwl_cfg iwl6000g2a_2agn_cfg = {
        .ht_params = &iwl6000_ht_params,
        .need_dc_calib = true,
        .need_temp_offset_calib = true,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6000g2a_2abg_cfg = {
@@ -578,6 +579,7 @@ struct iwl_cfg iwl6000g2a_2abg_cfg = {
        .base_params = &iwl6000_base_params,
        .need_dc_calib = true,
        .need_temp_offset_calib = true,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6000g2a_2bg_cfg = {
@@ -595,6 +597,7 @@ struct iwl_cfg iwl6000g2a_2bg_cfg = {
        .base_params = &iwl6000_base_params,
        .need_dc_calib = true,
        .need_temp_offset_calib = true,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6000g2b_2agn_cfg = {
@@ -616,6 +619,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
        .need_temp_offset_calib = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6000g2b_2abg_cfg = {
@@ -636,6 +640,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
        .need_temp_offset_calib = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6000g2b_2bgn_cfg = {
@@ -657,6 +662,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
        .need_temp_offset_calib = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6000g2b_2bg_cfg = {
@@ -677,6 +683,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
        .need_temp_offset_calib = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6000g2b_bgn_cfg = {
@@ -698,6 +705,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
        .need_temp_offset_calib = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6000g2b_bg_cfg = {
@@ -718,6 +726,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
        .need_temp_offset_calib = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .use_new_eeprom_reading = true,
 };
 
 /*
@@ -804,6 +813,7 @@ struct iwl_cfg iwl6050g2_bgn_cfg = {
        .base_params = &iwl6050_base_params,
        .ht_params = &iwl6000_ht_params,
        .need_dc_calib = true,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl6050_2abg_cfg = {
@@ -857,6 +867,7 @@ struct iwl_cfg iwl130_bgn_cfg = {
        .need_dc_calib = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .use_new_eeprom_reading = true,
 };
 
 struct iwl_cfg iwl130_bg_cfg = {
@@ -876,6 +887,7 @@ struct iwl_cfg iwl130_bg_cfg = {
        .need_dc_calib = true,
        /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
        .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
+       .use_new_eeprom_reading = true,
 };
 
 MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
index a650baba0809d1bf1d56d86f687f7dc07cf53d1b..9eeeda18748de6fb12a09cc5f5b74c90553a4bf4 100644 (file)
@@ -392,7 +392,7 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv,
 /**
  * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info
  */
-void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
+static void iwlcore_eeprom_enhanced_txpower_old(struct iwl_priv *priv)
 {
        int eeprom_section_count = 0;
        int section, element;
@@ -419,7 +419,8 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
                 * always check for valid entry before process
                 * the information
                 */
-               if (!enhanced_txpower->common || enhanced_txpower->reserved)
+               if (!(enhanced_txpower->flags || enhanced_txpower->channel) ||
+                   enhanced_txpower->delta_20_in_40)
                        continue;
 
                for (element = 0; element < eeprom_section_count; element++) {
@@ -452,3 +453,86 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
                }
        }
 }
+
+static void
+iwlcore_eeprom_enh_txp_read_element(struct iwl_priv *priv,
+                                   struct iwl_eeprom_enhanced_txpwr *txp,
+                                   s8 max_txpower_avg)
+{
+       int ch_idx;
+       bool is_ht40 = txp->flags & IWL_EEPROM_ENH_TXP_FL_40MHZ;
+       enum ieee80211_band band;
+
+       band = txp->flags & IWL_EEPROM_ENH_TXP_FL_BAND_52G ?
+               IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
+
+       for (ch_idx = 0; ch_idx < priv->channel_count; ch_idx++) {
+               struct iwl_channel_info *ch_info = &priv->channel_info[ch_idx];
+
+               /* update matching channel or from common data only */
+               if (txp->channel != 0 && ch_info->channel != txp->channel)
+                       continue;
+
+               /* update matching band only */
+               if (band != ch_info->band)
+                       continue;
+
+               if (ch_info->max_power_avg < max_txpower_avg && !is_ht40) {
+                       ch_info->max_power_avg = max_txpower_avg;
+                       ch_info->curr_txpow = max_txpower_avg;
+                       ch_info->scan_power = max_txpower_avg;
+               }
+
+               if (is_ht40 && ch_info->ht40_max_power_avg < max_txpower_avg)
+                       ch_info->ht40_max_power_avg = max_txpower_avg;
+       }
+}
+
+#define EEPROM_TXP_OFFS        (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT)
+#define EEPROM_TXP_ENTRY_LEN sizeof(struct iwl_eeprom_enhanced_txpwr)
+#define EEPROM_TXP_SZ_OFFS (0x00 | INDIRECT_ADDRESS | INDIRECT_TXP_LIMIT_SIZE)
+
+static void iwlcore_eeprom_enhanced_txpower_new(struct iwl_priv *priv)
+{
+       struct iwl_eeprom_enhanced_txpwr *txp_array, *txp;
+       int idx, entries;
+       __le16 *txp_len;
+       s8 max_txp_avg, max_txp_avg_halfdbm;
+
+       BUILD_BUG_ON(sizeof(struct iwl_eeprom_enhanced_txpwr) != 8);
+
+       /* the length is in 16-bit words, but we want entries */
+       txp_len = (__le16 *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_SZ_OFFS);
+       entries = le16_to_cpup(txp_len) * 2 / EEPROM_TXP_ENTRY_LEN;
+
+       txp_array = (void *) iwlagn_eeprom_query_addr(priv, EEPROM_TXP_OFFS);
+       for (idx = 0; idx < entries; idx++) {
+               txp = &txp_array[idx];
+
+               /* skip invalid entries */
+               if (!(txp->flags & IWL_EEPROM_ENH_TXP_FL_VALID))
+                       continue;
+
+               max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx,
+                                                     &max_txp_avg_halfdbm);
+
+               /*
+                * Update the user limit values values to the highest
+                * power supported by any channel
+                */
+               if (max_txp_avg > priv->tx_power_user_lmt)
+                       priv->tx_power_user_lmt = max_txp_avg;
+               if (max_txp_avg_halfdbm > priv->tx_power_lmt_in_half_dbm)
+                       priv->tx_power_lmt_in_half_dbm = max_txp_avg_halfdbm;
+
+               iwlcore_eeprom_enh_txp_read_element(priv, txp, max_txp_avg);
+       }
+}
+
+void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv)
+{
+       if (priv->cfg->use_new_eeprom_reading)
+               iwlcore_eeprom_enhanced_txpower_new(priv);
+       else
+               iwlcore_eeprom_enhanced_txpower_old(priv);
+}
index b555edd533547e3bf98eed8e948a276ef141aace..554afb7d9670dff564873b9509cd59c3058a346e 100644 (file)
@@ -569,6 +569,12 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
        case INDIRECT_REGULATORY:
                offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);
                break;
+       case INDIRECT_TXP_LIMIT:
+               offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT);
+               break;
+       case INDIRECT_TXP_LIMIT_SIZE:
+               offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE);
+               break;
        case INDIRECT_CALIBRATION:
                offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);
                break;
index 64527def059f7de76ac0e4bdcadd0147576805c1..954ecc2c34c41f239dc1d24932d67be68aa741fa 100644 (file)
@@ -390,6 +390,7 @@ struct iwl_cfg {
        const bool need_temp_offset_calib; /* if used set to true */
        u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
        u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
+       const bool use_new_eeprom_reading; /* temporary, remove later */
 };
 
 /***************************
index d9b590625ae4eb16ba996d0bbd8d794acc30dae9..e3a279d2d0b6307fcf5d38948454cb7ba8da29c7 100644 (file)
@@ -120,6 +120,17 @@ struct iwl_eeprom_channel {
        s8 max_power_avg;       /* max power (dBm) on this chnl, limit 31 */
 } __packed;
 
+enum iwl_eeprom_enhanced_txpwr_flags {
+       IWL_EEPROM_ENH_TXP_FL_VALID             = BIT(0),
+       IWL_EEPROM_ENH_TXP_FL_BAND_52G          = BIT(1),
+       IWL_EEPROM_ENH_TXP_FL_OFDM              = BIT(2),
+       IWL_EEPROM_ENH_TXP_FL_40MHZ             = BIT(3),
+       IWL_EEPROM_ENH_TXP_FL_HT_AP             = BIT(4),
+       IWL_EEPROM_ENH_TXP_FL_RES1              = BIT(5),
+       IWL_EEPROM_ENH_TXP_FL_RES2              = BIT(6),
+       IWL_EEPROM_ENH_TXP_FL_COMMON_TYPE       = BIT(7),
+};
+
 /**
  * iwl_eeprom_enhanced_txpwr structure
  *    This structure presents the enhanced regulatory tx power limit layout
@@ -127,21 +138,23 @@ struct iwl_eeprom_channel {
  *    Enhanced regulatory tx power portion of eeprom image can be broken down
  *    into individual structures; each one is 8 bytes in size and contain the
  *    following information
- * @common: (desc + channel) not used by driver, should _NOT_ be "zero"
+ * @flags: entry flags
+ * @channel: channel number
  * @chain_a_max_pwr: chain a max power in 1/2 dBm
  * @chain_b_max_pwr: chain b max power in 1/2 dBm
  * @chain_c_max_pwr: chain c max power in 1/2 dBm
- * @reserved: not used, should be "zero"
+ * @delta_20_in_40: 20-in-40 deltas (hi/lo)
  * @mimo2_max_pwr: mimo2 max power in 1/2 dBm
  * @mimo3_max_pwr: mimo3 max power in 1/2 dBm
  *
  */
 struct iwl_eeprom_enhanced_txpwr {
-       __le16 common;
+       u8 flags;
+       u8 channel;
        s8 chain_a_max;
        s8 chain_b_max;
        s8 chain_c_max;
-       s8 reserved;
+       u8 delta_20_in_40;
        s8 mimo2_max;
        s8 mimo3_max;
 } __packed;
@@ -186,6 +199,8 @@ struct iwl_eeprom_enhanced_txpwr {
 #define EEPROM_LINK_CALIBRATION      (2*0x67)
 #define EEPROM_LINK_PROCESS_ADJST    (2*0x68)
 #define EEPROM_LINK_OTHERS           (2*0x69)
+#define EEPROM_LINK_TXP_LIMIT        (2*0x6a)
+#define EEPROM_LINK_TXP_LIMIT_SIZE   (2*0x6b)
 
 /* agn regulatory - indirect access */
 #define EEPROM_REG_BAND_1_CHANNELS       ((0x08)\
@@ -389,6 +404,8 @@ struct iwl_eeprom_calib_info {
 #define INDIRECT_CALIBRATION        0x00040000
 #define INDIRECT_PROCESS_ADJST      0x00050000
 #define INDIRECT_OTHERS             0x00060000
+#define INDIRECT_TXP_LIMIT          0x00070000
+#define INDIRECT_TXP_LIMIT_SIZE     0x00080000
 #define INDIRECT_ADDRESS            0x00100000
 
 /* General */
index 373930afc26b50f2d7cddeb9027b07f8e5ad7775..113f4f204657ec911b6fe01c112f83f57d0d7fa8 100644 (file)
@@ -619,7 +619,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
                                     print_ssid(ssid_buf, ssid, ssid_len),
                                     LBS_SCAN_RSSI_TO_MBM(rssi)/100);
 
-                       if (channel ||
+                       if (channel &&
                            !(channel->flags & IEEE80211_CHAN_DISABLED))
                                cfg80211_inform_bss(wiphy, channel,
                                        bssid, le64_to_cpu(*(__le64 *)tsfdesc),
index d5bc21e5a02c7520d6599ad5822eafe85b267823..2325e56a9b0bd8cc35c7ee958be19ed5ff2adf2f 100644 (file)
@@ -43,6 +43,7 @@ MODULE_FIRMWARE("isl3887usb");
 
 static struct usb_device_id p54u_table[] __devinitdata = {
        /* Version 1 devices (pci chip + net2280) */
+       {USB_DEVICE(0x0411, 0x0050)},   /* Buffalo WLI2-USB2-G54 */
        {USB_DEVICE(0x045e, 0x00c2)},   /* Microsoft MN-710 */
        {USB_DEVICE(0x0506, 0x0a11)},   /* 3COM 3CRWE254G72 */
        {USB_DEVICE(0x06b9, 0x0120)},   /* Thomson SpeedTouch 120g */
@@ -56,9 +57,13 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x0846, 0x4220)},   /* Netgear WG111 */
        {USB_DEVICE(0x09aa, 0x1000)},   /* Spinnaker Proto board */
        {USB_DEVICE(0x0cde, 0x0006)},   /* Medion 40900, Roper Europe */
+       {USB_DEVICE(0x0db0, 0x6826)},   /* MSI UB54G (MS-6826) */
        {USB_DEVICE(0x107b, 0x55f2)},   /* Gateway WGU-210 (Gemtek) */
        {USB_DEVICE(0x124a, 0x4023)},   /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */
+       {USB_DEVICE(0x1435, 0x0210)},   /* Inventel UR054G */
+       {USB_DEVICE(0x15a9, 0x0002)},   /* Gemtek WUBI-100GW 802.11g */
        {USB_DEVICE(0x1630, 0x0005)},   /* 2Wire 802.11g USB (v1) / Z-Com */
+       {USB_DEVICE(0x182d, 0x096b)},   /* Sitecom WL-107 */
        {USB_DEVICE(0x1915, 0x2234)},   /* Linksys WUSB54G OEM */
        {USB_DEVICE(0x1915, 0x2235)},   /* Linksys WUSB54G Portable OEM */
        {USB_DEVICE(0x2001, 0x3701)},   /* DLink DWL-G120 Spinnaker */
@@ -94,6 +99,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x1435, 0x0427)},   /* Inventel UR054G */
        {USB_DEVICE(0x1668, 0x1050)},   /* Actiontec 802UIG-1 */
        {USB_DEVICE(0x2001, 0x3704)},   /* DLink DWL-G122 rev A2 */
+       {USB_DEVICE(0x2001, 0x3705)},   /* D-Link DWL-G120 rev C1 */
        {USB_DEVICE(0x413c, 0x5513)},   /* Dell WLA3310 USB Wireless Adapter */
        {USB_DEVICE(0x413c, 0x8102)},   /* Spinnaker DUT */
        {USB_DEVICE(0x413c, 0x8104)},   /* Cohiba Proto board */
index b267395359863ca10a55fe8a39f186e5bf08deb9..09a67905c230e5f9a9029ba2c786a707d73b5108 100644 (file)
@@ -912,6 +912,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
        __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags);
        __set_bit(DRIVER_REQUIRE_TXSTATUS_FIFO, &rt2x00dev->flags);
+       __set_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags);
        if (!modparam_nohwcrypt)
                __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
        __set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
index 94fe589acfaabff06eac097fe7e3ae3e2f7ea310..ab43e7ca2a231000ba0d40489860f950883be16d 100644 (file)
@@ -664,6 +664,7 @@ enum rt2x00_flags {
        DRIVER_REQUIRE_COPY_IV,
        DRIVER_REQUIRE_L2PAD,
        DRIVER_REQUIRE_TXSTATUS_FIFO,
+       DRIVER_REQUIRE_TASKLET_CONTEXT,
 
        /*
         * Driver features
index 5ba79b935f09f5bed56f999653338501584cf141..d019830ca8407c2aa10ed0ae95abe8679c654e55 100644 (file)
@@ -390,9 +390,12 @@ void rt2x00lib_txdone(struct queue_entry *entry,
         * through a mac80211 library call (RTS/CTS) then we should not
         * send the status report back.
         */
-       if (!(skbdesc_flags & SKBDESC_NOT_MAC80211))
-               ieee80211_tx_status(rt2x00dev->hw, entry->skb);
-       else
+       if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) {
+               if (test_bit(DRIVER_REQUIRE_TASKLET_CONTEXT, &rt2x00dev->flags))
+                       ieee80211_tx_status(rt2x00dev->hw, entry->skb);
+               else
+                       ieee80211_tx_status_ni(rt2x00dev->hw, entry->skb);
+       } else
                dev_kfree_skb_any(entry->skb);
 
        /*
index cd1b3dcd61db67671e28df47cae7a19293fa881f..ec47e22fa186ce89ed7c2758998e6ff008d140aa 100644 (file)
@@ -744,7 +744,7 @@ static int yellowfin_init_ring(struct net_device *dev)
        }
 
        for (i = 0; i < RX_RING_SIZE; i++) {
-               struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz);
+               struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz + 2);
                yp->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
@@ -1157,7 +1157,7 @@ static int yellowfin_rx(struct net_device *dev)
        for (; yp->cur_rx - yp->dirty_rx > 0; yp->dirty_rx++) {
                entry = yp->dirty_rx % RX_RING_SIZE;
                if (yp->rx_skbuff[entry] == NULL) {
-                       struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz);
+                       struct sk_buff *skb = dev_alloc_skb(yp->rx_buf_sz + 2);
                        if (skb == NULL)
                                break;                          /* Better luck next round. */
                        yp->rx_skbuff[entry] = skb;
index c85d3c7421fc94796c6814d0c453b33f831a9279..f37fbeb66a4400c2c7fa28bc45cd8be5af7c7c47 100644 (file)
@@ -61,7 +61,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
                info.of_node = of_node_get(node);
                info.archdata = &dev_ad;
 
-               request_module("%s", info.type);
+               request_module("%s%s", I2C_MODULE_PREFIX, info.type);
 
                result = i2c_new_device(adap, &info);
                if (result == NULL) {
index 003170ea2e394193bdcb7af4033a98bca9d46127..69546e9213dd7727d7b0db8f9cd56d1772ea7431 100644 (file)
@@ -64,77 +64,6 @@ void pci_bus_remove_resources(struct pci_bus *bus)
        }
 }
 
-static bool pci_bus_resource_better(struct resource *res1, bool pos1,
-                                   struct resource *res2, bool pos2)
-{
-       /* If exactly one is positive decode, always prefer that one */
-       if (pos1 != pos2)
-               return pos1 ? true : false;
-
-       /* Prefer the one that contains the highest address */
-       if (res1->end != res2->end)
-               return (res1->end > res2->end) ? true : false;
-
-       /* Otherwise, prefer the one with highest "center of gravity" */
-       if (res1->start != res2->start)
-               return (res1->start > res2->start) ? true : false;
-
-       /* Otherwise, choose one arbitrarily (but consistently) */
-       return (res1 > res2) ? true : false;
-}
-
-static bool pci_bus_resource_positive(struct pci_bus *bus, struct resource *res)
-{
-       struct pci_bus_resource *bus_res;
-
-       /*
-        * This relies on the fact that pci_bus.resource[] refers to P2P or
-        * CardBus bridge base/limit registers, which are always positively
-        * decoded.  The pci_bus.resources list contains host bridge or
-        * subtractively decoded resources.
-        */
-       list_for_each_entry(bus_res, &bus->resources, list) {
-               if (bus_res->res == res)
-                       return (bus_res->flags & PCI_SUBTRACTIVE_DECODE) ?
-                               false : true;
-       }
-       return true;
-}
-
-/*
- * Find the next-best bus resource after the cursor "res".  If the cursor is
- * NULL, return the best resource.  "Best" means that we prefer positive
- * decode regions over subtractive decode, then those at higher addresses.
- */
-static struct resource *pci_bus_find_resource_prev(struct pci_bus *bus,
-                                                  unsigned int type,
-                                                  struct resource *res)
-{
-       bool res_pos, r_pos, prev_pos = false;
-       struct resource *r, *prev = NULL;
-       int i;
-
-       res_pos = pci_bus_resource_positive(bus, res);
-       pci_bus_for_each_resource(bus, r, i) {
-               if (!r)
-                       continue;
-
-               if ((r->flags & IORESOURCE_TYPE_BITS) != type)
-                       continue;
-
-               r_pos = pci_bus_resource_positive(bus, r);
-               if (!res || pci_bus_resource_better(res, res_pos, r, r_pos)) {
-                       if (!prev || pci_bus_resource_better(r, r_pos,
-                                                            prev, prev_pos)) {
-                               prev = r;
-                               prev_pos = r_pos;
-                       }
-               }
-       }
-
-       return prev;
-}
-
 /**
  * pci_bus_alloc_resource - allocate a resource from a parent bus
  * @bus: PCI bus
@@ -160,10 +89,9 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
                                          resource_size_t),
                void *alignf_data)
 {
-       int ret = -ENOMEM;
+       int i, ret = -ENOMEM;
        struct resource *r;
        resource_size_t max = -1;
-       unsigned int type = res->flags & IORESOURCE_TYPE_BITS;
 
        type_mask |= IORESOURCE_IO | IORESOURCE_MEM;
 
@@ -171,9 +99,10 @@ pci_bus_alloc_resource(struct pci_bus *bus, struct resource *res,
        if (!(res->flags & IORESOURCE_MEM_64))
                max = PCIBIOS_MAX_MEM_32;
 
-       /* Look for space at highest addresses first */
-       r = pci_bus_find_resource_prev(bus, type, NULL);
-       for ( ; r; r = pci_bus_find_resource_prev(bus, type, r)) {
+       pci_bus_for_each_resource(bus, r, i) {
+               if (!r)
+                       continue;
+
                /* type_mask must match */
                if ((res->flags ^ r->flags) & type_mask)
                        continue;
index 0157708d474da57ad0532a3bb8bbbd90f0204aeb..09933eb9126be48f154e809bdcfdc57292a4858a 100644 (file)
@@ -1417,6 +1417,11 @@ int __init enable_drhd_fault_handling(void)
                               (unsigned long long)drhd->reg_base_addr, ret);
                        return -1;
                }
+
+               /*
+                * Clear any previous faults.
+                */
+               dmar_fault(iommu->irq, iommu);
        }
 
        return 0;
index 2574700db461559717a95e0623c1c58c5821c687..5f7226223a62c9067bcc4a47f1b3e6bd47b69c40 100644 (file)
@@ -115,7 +115,8 @@ static struct pcie_port_service_driver __initdata dummy_driver = {
 static int __init select_detection_mode(void)
 {
        struct dummy_slot *slot, *tmp;
-       pcie_port_service_register(&dummy_driver);
+       if (pcie_port_service_register(&dummy_driver))
+               return PCIEHP_DETECT_ACPI;
        pcie_port_service_unregister(&dummy_driver);
        list_for_each_entry_safe(slot, tmp, &dummy_slots, list) {
                list_del(&slot->list);
index 6f9350cabbd51d1574ec52bcf287d4065f8b3c36..53a786fd0d40c88d978bd4a656971be7b09cdb4a 100644 (file)
@@ -2329,6 +2329,9 @@ static void __devinit nvbridge_check_legacy_irq_routing(struct pci_dev *dev)
 {
        u32 cfg;
 
+       if (!pci_find_capability(dev, PCI_CAP_ID_HT))
+               return;
+
        pci_read_config_dword(dev, 0x74, &cfg);
 
        if (cfg & ((1 << 2) | (1 << 15))) {
@@ -2764,6 +2767,29 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_m
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
 #endif /*CONFIG_MMC_RICOH_MMC*/
 
+#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
+#define VTUNCERRMSK_REG        0x1ac
+#define VTD_MSK_SPEC_ERRORS    (1 << 31)
+/*
+ * This is a quirk for masking vt-d spec defined errors to platform error
+ * handling logic. With out this, platforms using Intel 7500, 5500 chipsets
+ * (and the derivative chipsets like X58 etc) seem to generate NMI/SMI (based
+ * on the RAS config settings of the platform) when a vt-d fault happens.
+ * The resulting SMI caused the system to hang.
+ *
+ * VT-d spec related errors are already handled by the VT-d OS code, so no
+ * need to report the same error through other channels.
+ */
+static void vtd_mask_spec_errors(struct pci_dev *dev)
+{
+       u32 word;
+
+       pci_read_config_dword(dev, VTUNCERRMSK_REG, &word);
+       pci_write_config_dword(dev, VTUNCERRMSK_REG, word | VTD_MSK_SPEC_ERRORS);
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
+#endif
 
 static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
                          struct pci_fixup *end)
index 9a44a90dcf7a36f069739dc14c999681ae8b50d0..29935ea921df289e7eae7e5fb0a2e3fe88d261f0 100644 (file)
@@ -50,8 +50,9 @@ sa1111_cs-$(CONFIG_SA1100_JORNADA720)         += sa1100_jornada720.o
 sa1100_cs-y                                    += sa1100_generic.o
 sa1100_cs-$(CONFIG_SA1100_ASSABET)             += sa1100_assabet.o
 sa1100_cs-$(CONFIG_SA1100_CERF)                        += sa1100_cerf.o
-sa1100_cs-$(CONFIG_SA1100_COLLIE)              += pxa2xx_sharpsl.o
+sa1100_cs-$(CONFIG_SA1100_COLLIE)              += pxa2xx_sharpsl.o
 sa1100_cs-$(CONFIG_SA1100_H3600)               += sa1100_h3600.o
+sa1100_cs-$(CONFIG_SA1100_NANOENGINE)          += sa1100_nanoengine.o
 sa1100_cs-$(CONFIG_SA1100_SHANNON)             += sa1100_shannon.o
 sa1100_cs-$(CONFIG_SA1100_SIMPAD)              += sa1100_simpad.o
 
index 6b228590b3fddb5bbd044acd561a029f99bb328d..fb9740d3e9a76e5b30317860ebafee954eef0a6c 100644 (file)
@@ -53,6 +53,9 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = {
 #if defined(CONFIG_SA1100_H3100) || defined(CONFIG_SA1100_H3600)
        pcmcia_h3600_init,
 #endif
+#ifdef CONFIG_SA1100_NANOENGINE
+       pcmcia_nanoengine_init,
+#endif
 #ifdef CONFIG_SA1100_SHANNON
        pcmcia_shannon_init,
 #endif
index 794f96a35bbafb1a78b5c292a2bc94852db0ee7c..adb08dbc723f63384e2924cdf5213e3f2855c054 100644 (file)
@@ -13,6 +13,7 @@ extern int pcmcia_freebird_init(struct device *);
 extern int pcmcia_gcplus_init(struct device *);
 extern int pcmcia_graphicsmaster_init(struct device *);
 extern int pcmcia_h3600_init(struct device *);
+extern int pcmcia_nanoengine_init(struct device *);
 extern int pcmcia_pangolin_init(struct device *);
 extern int pcmcia_pfs168_init(struct device *);
 extern int pcmcia_shannon_init(struct device *);
diff --git a/drivers/pcmcia/sa1100_nanoengine.c b/drivers/pcmcia/sa1100_nanoengine.c
new file mode 100644 (file)
index 0000000..3d2652e
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * drivers/pcmcia/sa1100_nanoengine.c
+ *
+ * PCMCIA implementation routines for BSI nanoEngine.
+ *
+ * In order to have a fully functional pcmcia subsystem in a BSE nanoEngine
+ * board you should carefully read this:
+ * http://cambuca.ldhs.cetuc.puc-rio.br/nanoengine/
+ *
+ * Copyright (C) 2010 Marcelo Roberto Jimenez <mroberto@cpti.cetuc.puc-rio.br>
+ *
+ * Based on original work for kernel 2.4 by
+ * Miguel Freitas <miguel@cpti.cetuc.puc-rio.br>
+ *
+ * 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/device.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+
+#include <mach/hardware.h>
+#include <mach/nanoengine.h>
+
+#include "sa1100_generic.h"
+
+static struct pcmcia_irqs irqs_skt0[] = {
+       /* socket, IRQ, name */
+       { 0, NANOENGINE_IRQ_GPIO_PC_CD0, "PC CD0" },
+};
+
+static struct pcmcia_irqs irqs_skt1[] = {
+       /* socket, IRQ, name */
+       { 1, NANOENGINE_IRQ_GPIO_PC_CD1, "PC CD1" },
+};
+
+struct nanoengine_pins {
+       unsigned input_pins;
+       unsigned output_pins;
+       unsigned clear_outputs;
+       unsigned transition_pins;
+       unsigned pci_irq;
+       struct pcmcia_irqs *pcmcia_irqs;
+       unsigned pcmcia_irqs_size;
+};
+
+static struct nanoengine_pins nano_skts[] = {
+       {
+               .input_pins             = GPIO_PC_READY0 | GPIO_PC_CD0,
+               .output_pins            = GPIO_PC_RESET0,
+               .clear_outputs          = GPIO_PC_RESET0,
+               .transition_pins        = NANOENGINE_IRQ_GPIO_PC_CD0,
+               .pci_irq                = NANOENGINE_IRQ_GPIO_PC_READY0,
+               .pcmcia_irqs            = irqs_skt0,
+               .pcmcia_irqs_size       = ARRAY_SIZE(irqs_skt0)
+       }, {
+               .input_pins             = GPIO_PC_READY1 | GPIO_PC_CD1,
+               .output_pins            = GPIO_PC_RESET1,
+               .clear_outputs          = GPIO_PC_RESET1,
+               .transition_pins        = NANOENGINE_IRQ_GPIO_PC_CD1,
+               .pci_irq                = NANOENGINE_IRQ_GPIO_PC_READY1,
+               .pcmcia_irqs            = irqs_skt1,
+               .pcmcia_irqs_size       = ARRAY_SIZE(irqs_skt1)
+       }
+};
+
+unsigned num_nano_pcmcia_sockets = ARRAY_SIZE(nano_skts);
+
+static int nanoengine_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
+{
+       unsigned i = skt->nr;
+
+       if (i >= num_nano_pcmcia_sockets)
+               return -ENXIO;
+
+       GPDR &= ~nano_skts[i].input_pins;
+       GPDR |= nano_skts[i].output_pins;
+       GPCR = nano_skts[i].clear_outputs;
+       set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
+       skt->socket.pci_irq = nano_skts[i].pci_irq;
+
+       return soc_pcmcia_request_irqs(skt,
+               nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+/*
+ * Release all resources.
+ */
+static void nanoengine_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
+{
+       unsigned i = skt->nr;
+
+       if (i >= num_nano_pcmcia_sockets)
+               return;
+
+       soc_pcmcia_free_irqs(skt,
+               nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+static int nanoengine_pcmcia_configure_socket(
+       struct soc_pcmcia_socket *skt, const socket_state_t *state)
+{
+       unsigned reset;
+       unsigned i = skt->nr;
+
+       if (i >= num_nano_pcmcia_sockets)
+               return -ENXIO;
+
+       switch (i) {
+       case 0:
+               reset = GPIO_PC_RESET0;
+               break;
+       case 1:
+               reset = GPIO_PC_RESET1;
+               break;
+       default:
+               return -ENXIO;
+       }
+
+       if (state->flags & SS_RESET)
+               GPSR = reset;
+       else
+               GPCR = reset;
+
+       return 0;
+}
+
+static void nanoengine_pcmcia_socket_state(
+       struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
+{
+       unsigned long levels = GPLR;
+       unsigned i = skt->nr;
+
+       if (i >= num_nano_pcmcia_sockets)
+               return;
+
+       memset(state, 0, sizeof(struct pcmcia_state));
+       switch (i) {
+       case 0:
+               state->ready = (levels & GPIO_PC_READY0) ? 1 : 0;
+               state->detect = !(levels & GPIO_PC_CD0) ? 1 : 0;
+               break;
+       case 1:
+               state->ready = (levels & GPIO_PC_READY1) ? 1 : 0;
+               state->detect = !(levels & GPIO_PC_CD1) ? 1 : 0;
+               break;
+       default:
+               return;
+       }
+       state->bvd1 = 1;
+       state->bvd2 = 1;
+       state->wrprot = 0; /* Not available */
+       state->vs_3v = 1; /* Can only apply 3.3V */
+       state->vs_Xv = 0;
+}
+
+/*
+ * Enable card status IRQs on (re-)initialisation.  This can
+ * be called at initialisation, power management event, or
+ * pcmcia event.
+ */
+static void nanoengine_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
+{
+       unsigned i = skt->nr;
+
+       if (i >= num_nano_pcmcia_sockets)
+               return;
+
+       soc_pcmcia_enable_irqs(skt,
+               nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+/*
+ * Disable card status IRQs on suspend.
+ */
+static void nanoengine_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
+{
+       unsigned i = skt->nr;
+
+       if (i >= num_nano_pcmcia_sockets)
+               return;
+
+       soc_pcmcia_disable_irqs(skt,
+               nano_skts[i].pcmcia_irqs, nano_skts[i].pcmcia_irqs_size);
+}
+
+static struct pcmcia_low_level nanoengine_pcmcia_ops = {
+       .owner                  = THIS_MODULE,
+
+       .hw_init                = nanoengine_pcmcia_hw_init,
+       .hw_shutdown            = nanoengine_pcmcia_hw_shutdown,
+
+       .configure_socket       = nanoengine_pcmcia_configure_socket,
+       .socket_state           = nanoengine_pcmcia_socket_state,
+       .socket_init            = nanoengine_pcmcia_socket_init,
+       .socket_suspend         = nanoengine_pcmcia_socket_suspend,
+};
+
+int pcmcia_nanoengine_init(struct device *dev)
+{
+       int ret = -ENODEV;
+
+       if (machine_is_nanoengine())
+               ret = sa11xx_drv_pcmcia_probe(
+                       dev, &nanoengine_pcmcia_ops, 0, 2);
+
+       return ret;
+}
+
index 2fe8cb8e95cd3409d74d04e312388736234c5d0c..5a9a392eacdf18d1ba9de1237f11f0a3efefbf7d 100644 (file)
 ======================================================================*/
 
 
-#include <linux/module.h>
-#include <linux/moduleparam.h>
+#include <linux/cpufreq.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
 #include <linux/kernel.h>
-#include <linux/timer.h>
 #include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/mutex.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
 #include <linux/spinlock.h>
-#include <linux/cpufreq.h>
+#include <linux/timer.h>
 
 #include <mach/hardware.h>
-#include <asm/io.h>
 #include <asm/system.h>
 
 #include "soc_common.h"
@@ -74,7 +74,8 @@ EXPORT_SYMBOL(soc_pcmcia_debug);
 
 #endif
 
-#define to_soc_pcmcia_socket(x)        container_of(x, struct soc_pcmcia_socket, socket)
+#define to_soc_pcmcia_socket(x)        \
+       container_of(x, struct soc_pcmcia_socket, socket)
 
 static unsigned short
 calc_speed(unsigned short *spds, int num, unsigned short dflt)
@@ -91,11 +92,15 @@ calc_speed(unsigned short *spds, int num, unsigned short dflt)
        return speed;
 }
 
-void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt, struct soc_pcmcia_timing *timing)
+void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
+       struct soc_pcmcia_timing *timing)
 {
-       timing->io = calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
-       timing->mem = calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
-       timing->attr = calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+       timing->io =
+               calc_speed(skt->spd_io, MAX_IO_WIN, SOC_PCMCIA_IO_ACCESS);
+       timing->mem =
+               calc_speed(skt->spd_mem, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
+       timing->attr =
+               calc_speed(skt->spd_attr, MAX_WIN, SOC_PCMCIA_3V_MEM_ACCESS);
 }
 EXPORT_SYMBOL(soc_common_pcmcia_get_timing);
 
@@ -137,8 +142,8 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
  *
  * Convert PCMCIA socket state to our socket configure structure.
  */
-static int
-soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *state)
+static int soc_common_pcmcia_config_skt(
+       struct soc_pcmcia_socket *skt, socket_state_t *state)
 {
        int ret;
 
@@ -150,7 +155,8 @@ soc_common_pcmcia_config_skt(struct soc_pcmcia_socket *skt, socket_state_t *stat
                 */
                if (skt->irq_state != 1 && state->io_irq) {
                        skt->irq_state = 1;
-                       set_irq_type(skt->socket.pci_irq, IRQ_TYPE_EDGE_FALLING);
+                       set_irq_type(skt->socket.pci_irq,
+                               IRQ_TYPE_EDGE_FALLING);
                } else if (skt->irq_state == 1 && state->io_irq == 0) {
                        skt->irq_state = 0;
                        set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
@@ -304,24 +310,24 @@ soc_common_pcmcia_get_status(struct pcmcia_socket *sock, unsigned int *status)
  * of power configuration, reset, &c. We also record the value of
  * `state' in order to regurgitate it to the PCMCIA core later.
  */
-static int
-soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
+static int soc_common_pcmcia_set_socket(
+       struct pcmcia_socket *sock, socket_state_t *state)
 {
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
 
-       debug(skt, 2, "mask: %s%s%s%s%s%sflags: %s%s%s%s%s%sVcc %d Vpp %d irq %d\n",
-                       (state->csc_mask==0)?"<NONE> ":"",
-                       (state->csc_mask&SS_DETECT)?"DETECT ":"",
-                       (state->csc_mask&SS_READY)?"READY ":"",
-                       (state->csc_mask&SS_BATDEAD)?"BATDEAD ":"",
-                       (state->csc_mask&SS_BATWARN)?"BATWARN ":"",
-                       (state->csc_mask&SS_STSCHG)?"STSCHG ":"",
-                       (state->flags==0)?"<NONE> ":"",
-                       (state->flags&SS_PWR_AUTO)?"PWR_AUTO ":"",
-                       (state->flags&SS_IOCARD)?"IOCARD ":"",
-                       (state->flags&SS_RESET)?"RESET ":"",
-                       (state->flags&SS_SPKR_ENA)?"SPKR_ENA ":"",
-                       (state->flags&SS_OUTPUT_ENA)?"OUTPUT_ENA ":"",
+       debug(skt, 2, "mask: %s%s%s%s%s%s flags: %s%s%s%s%s%s Vcc %d Vpp %d irq %d\n",
+                       (state->csc_mask == 0)          ? "<NONE> " :   "",
+                       (state->csc_mask & SS_DETECT)   ? "DETECT " :   "",
+                       (state->csc_mask & SS_READY)    ? "READY " :    "",
+                       (state->csc_mask & SS_BATDEAD)  ? "BATDEAD " :  "",
+                       (state->csc_mask & SS_BATWARN)  ? "BATWARN " :  "",
+                       (state->csc_mask & SS_STSCHG)   ? "STSCHG " :   "",
+                       (state->flags == 0)             ? "<NONE> " :   "",
+                       (state->flags & SS_PWR_AUTO)    ? "PWR_AUTO " : "",
+                       (state->flags & SS_IOCARD)      ? "IOCARD " :   "",
+                       (state->flags & SS_RESET)       ? "RESET " :    "",
+                       (state->flags & SS_SPKR_ENA)    ? "SPKR_ENA " : "",
+                       (state->flags & SS_OUTPUT_ENA)  ? "OUTPUT_ENA " : "",
                        state->Vcc, state->Vpp, state->io_irq);
 
        return soc_common_pcmcia_config_skt(skt, state);
@@ -336,8 +342,8 @@ soc_common_pcmcia_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
  *
  * Returns: 0 on success, -1 on error
  */
-static int
-soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *map)
+static int soc_common_pcmcia_set_io_map(
+       struct pcmcia_socket *sock, struct pccard_io_map *map)
 {
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
        unsigned short speed = map->speed;
@@ -346,14 +352,14 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
                map->map, map->speed, (unsigned long long)map->start,
                (unsigned long long)map->stop);
        debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
-               (map->flags==0)?"<NONE>":"",
-               (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-               (map->flags&MAP_16BIT)?"16BIT ":"",
-               (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-               (map->flags&MAP_0WS)?"0WS ":"",
-               (map->flags&MAP_WRPROT)?"WRPROT ":"",
-               (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"",
-               (map->flags&MAP_PREFETCH)?"PREFETCH ":"");
+               (map->flags == 0)               ? "<NONE>"      : "",
+               (map->flags & MAP_ACTIVE)       ? "ACTIVE "     : "",
+               (map->flags & MAP_16BIT)        ? "16BIT "      : "",
+               (map->flags & MAP_AUTOSZ)       ? "AUTOSZ "     : "",
+               (map->flags & MAP_0WS)          ? "0WS "        : "",
+               (map->flags & MAP_WRPROT)       ? "WRPROT "     : "",
+               (map->flags & MAP_USE_WAIT)     ? "USE_WAIT "   : "",
+               (map->flags & MAP_PREFETCH)     ? "PREFETCH "   : "");
 
        if (map->map >= MAX_IO_WIN) {
                printk(KERN_ERR "%s(): map (%d) out of range\n", __func__,
@@ -390,8 +396,8 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
  *
  * Returns: 0 on success, -ERRNO on error
  */
-static int
-soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *map)
+static int soc_common_pcmcia_set_mem_map(
+       struct pcmcia_socket *sock, struct pccard_mem_map *map)
 {
        struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
        struct resource *res;
@@ -400,14 +406,14 @@ soc_common_pcmcia_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map
        debug(skt, 2, "map %u speed %u card_start %08x\n",
                map->map, map->speed, map->card_start);
        debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
-               (map->flags==0)?"<NONE>":"",
-               (map->flags&MAP_ACTIVE)?"ACTIVE ":"",
-               (map->flags&MAP_16BIT)?"16BIT ":"",
-               (map->flags&MAP_AUTOSZ)?"AUTOSZ ":"",
-               (map->flags&MAP_0WS)?"0WS ":"",
-               (map->flags&MAP_WRPROT)?"WRPROT ":"",
-               (map->flags&MAP_ATTRIB)?"ATTRIB ":"",
-               (map->flags&MAP_USE_WAIT)?"USE_WAIT ":"");
+               (map->flags == 0)               ? "<NONE>"      : "",
+               (map->flags & MAP_ACTIVE)       ? "ACTIVE "     : "",
+               (map->flags & MAP_16BIT)        ? "16BIT "      : "",
+               (map->flags & MAP_AUTOSZ)       ? "AUTOSZ "     : "",
+               (map->flags & MAP_0WS)          ? "0WS "        : "",
+               (map->flags & MAP_WRPROT)       ? "WRPROT "     : "",
+               (map->flags & MAP_ATTRIB)       ? "ATTRIB "     : "",
+               (map->flags & MAP_USE_WAIT)     ? "USE_WAIT "   : "");
 
        if (map->map >= MAX_WIN)
                return -EINVAL;
@@ -462,8 +468,8 @@ static struct bittbl conf_bits[] = {
        { SS_OUTPUT_ENA,        "SS_OUTPUT_ENA" },
 };
 
-static void
-dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, int sz)
+static void dump_bits(char **p, const char *prefix,
+       unsigned int val, struct bittbl *bits, int sz)
 {
        char *b = *p;
        int i;
@@ -481,13 +487,14 @@ dump_bits(char **p, const char *prefix, unsigned int val, struct bittbl *bits, i
  *
  * Returns: the number of characters added to the buffer
  */
-static ssize_t show_status(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_status(
+       struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct soc_pcmcia_socket *skt =
                container_of(dev, struct soc_pcmcia_socket, socket.dev);
        char *p = buf;
 
-       p+=sprintf(p, "slot     : %d\n", skt->nr);
+       p += sprintf(p, "slot     : %d\n", skt->nr);
 
        dump_bits(&p, "status", skt->status,
                  status_bits, ARRAY_SIZE(status_bits));
@@ -496,12 +503,12 @@ static ssize_t show_status(struct device *dev, struct device_attribute *attr, ch
        dump_bits(&p, "cs_flags", skt->cs_state.flags,
                  conf_bits, ARRAY_SIZE(conf_bits));
 
-       p+=sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
-       p+=sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
-       p+=sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq,
+       p += sprintf(p, "Vcc      : %d\n", skt->cs_state.Vcc);
+       p += sprintf(p, "Vpp      : %d\n", skt->cs_state.Vpp);
+       p += sprintf(p, "IRQ      : %d (%d)\n", skt->cs_state.io_irq,
                skt->socket.pci_irq);
        if (skt->ops->show_timing)
-               p+=skt->ops->show_timing(skt, p);
+               p += skt->ops->show_timing(skt, p);
 
        return p-buf;
 }
@@ -594,7 +601,7 @@ soc_pcmcia_notifier(struct notifier_block *nb, unsigned long val, void *data)
 
        mutex_lock(&soc_pcmcia_sockets_lock);
        list_for_each_entry(skt, &soc_pcmcia_sockets, node)
-               if ( skt->ops->frequency_change )
+               if (skt->ops->frequency_change)
                        ret += skt->ops->frequency_change(skt, val, freqs);
        mutex_unlock(&soc_pcmcia_sockets_lock);
 
@@ -620,7 +627,8 @@ fs_initcall(soc_pcmcia_cpufreq_register);
 
 static void soc_pcmcia_cpufreq_unregister(void)
 {
-       cpufreq_unregister_notifier(&soc_pcmcia_notifier_block, CPUFREQ_TRANSITION_NOTIFIER);
+       cpufreq_unregister_notifier(&soc_pcmcia_notifier_block,
+               CPUFREQ_TRANSITION_NOTIFIER);
 }
 module_exit(soc_pcmcia_cpufreq_unregister);
 
index c44a5e8b8b82da9d06706d9cd3a3ec0fcb2b883c..f0b3ad13c273fb73394cc78ca8fb36521a8a4c90 100644 (file)
@@ -75,6 +75,7 @@
 #include <drm/i915_drm.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
+#include "intel_ips.h"
 
 #define PCI_DEVICE_ID_INTEL_THERMAL_SENSOR 0x3b32
 
 #define thm_writel(off, val) writel((val), ips->regmap + (off))
 
 static const int IPS_ADJUST_PERIOD = 5000; /* ms */
+static bool late_i915_load = false;
 
 /* For initial average collection */
 static const int IPS_SAMPLE_PERIOD = 200; /* ms */
@@ -339,6 +341,9 @@ struct ips_driver {
        u64 orig_turbo_ratios;
 };
 
+static bool
+ips_gpu_turbo_enabled(struct ips_driver *ips);
+
 /**
  * ips_cpu_busy - is CPU busy?
  * @ips: IPS driver struct
@@ -517,7 +522,7 @@ static void ips_disable_cpu_turbo(struct ips_driver *ips)
  */
 static bool ips_gpu_busy(struct ips_driver *ips)
 {
-       if (!ips->gpu_turbo_enabled)
+       if (!ips_gpu_turbo_enabled(ips))
                return false;
 
        return ips->gpu_busy();
@@ -532,7 +537,7 @@ static bool ips_gpu_busy(struct ips_driver *ips)
  */
 static void ips_gpu_raise(struct ips_driver *ips)
 {
-       if (!ips->gpu_turbo_enabled)
+       if (!ips_gpu_turbo_enabled(ips))
                return;
 
        if (!ips->gpu_raise())
@@ -549,7 +554,7 @@ static void ips_gpu_raise(struct ips_driver *ips)
  */
 static void ips_gpu_lower(struct ips_driver *ips)
 {
-       if (!ips->gpu_turbo_enabled)
+       if (!ips_gpu_turbo_enabled(ips))
                return;
 
        if (!ips->gpu_lower())
@@ -1454,6 +1459,31 @@ out_err:
        return false;
 }
 
+static bool
+ips_gpu_turbo_enabled(struct ips_driver *ips)
+{
+       if (!ips->gpu_busy && late_i915_load) {
+               if (ips_get_i915_syms(ips)) {
+                       dev_info(&ips->dev->dev,
+                                "i915 driver attached, reenabling gpu turbo\n");
+                       ips->gpu_turbo_enabled = !(thm_readl(THM_HTS) & HTS_GTD_DIS);
+               }
+       }
+
+       return ips->gpu_turbo_enabled;
+}
+
+void
+ips_link_to_i915_driver()
+{
+       /* We can't cleanly get at the various ips_driver structs from
+        * this caller (the i915 driver), so just set a flag saying
+        * that it's time to try getting the symbols again.
+        */
+       late_i915_load = true;
+}
+EXPORT_SYMBOL_GPL(ips_link_to_i915_driver);
+
 static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL,
                     PCI_DEVICE_ID_INTEL_THERMAL_SENSOR), },
diff --git a/drivers/platform/x86/intel_ips.h b/drivers/platform/x86/intel_ips.h
new file mode 100644 (file)
index 0000000..73299be
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2010 Intel Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * The full GNU General Public License is included in this distribution in
+ * the file called "COPYING".
+ */
+
+void ips_link_to_i915_driver(void);
index 90cf0a6ff23e3cce363958cb0c3e81cde08c14af..dd14e202c2c8cbaafe4ed261cab01835a16f8f89 100644 (file)
@@ -207,7 +207,7 @@ static int rs5c372_get_datetime(struct i2c_client *client, struct rtc_time *tm)
 static int rs5c372_set_datetime(struct i2c_client *client, struct rtc_time *tm)
 {
        struct rs5c372  *rs5c = i2c_get_clientdata(client);
-       unsigned char   buf[8];
+       unsigned char   buf[7];
        int             addr;
 
        dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d "
index e4a44b641702677ba99884f03089477f1c04f3cd..88ea52b8647ad358bb99e9c032f7764a9841080b 100644 (file)
 #include <mach/regs-ost.h>
 #endif
 
-#define RTC_DEF_DIVIDER                32768 - 1
+#define RTC_DEF_DIVIDER                (32768 - 1)
 #define RTC_DEF_TRIM           0
 
-static unsigned long rtc_freq = 1024;
+static const unsigned long RTC_FREQ = 1024;
 static unsigned long timer_freq;
 static struct rtc_time rtc_alarm;
 static DEFINE_SPINLOCK(sa1100_rtc_lock);
@@ -61,7 +61,8 @@ static inline int rtc_periodic_alarm(struct rtc_time *tm)
  * Calculate the next alarm time given the requested alarm time mask
  * and the current time.
  */
-static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now, struct rtc_time *alrm)
+static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
+       struct rtc_time *alrm)
 {
        unsigned long next_time;
        unsigned long now_time;
@@ -116,7 +117,23 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
        rtsr = RTSR;
        /* clear interrupt sources */
        RTSR = 0;
-       RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+       /* Fix for a nasty initialization problem the in SA11xx RTSR register.
+        * See also the comments in sa1100_rtc_probe(). */
+       if (rtsr & (RTSR_ALE | RTSR_HZE)) {
+               /* This is the original code, before there was the if test
+                * above. This code does not clear interrupts that were not
+                * enabled. */
+               RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+       } else {
+               /* For some reason, it is possible to enter this routine
+                * without interruptions enabled, it has been tested with
+                * several units (Bug in SA11xx chip?).
+                *
+                * This situation leads to an infinite "loop" of interrupt
+                * routine calling and as a result the processor seems to
+                * lock on its first call to open(). */
+               RTSR = RTSR_AL | RTSR_HZ;
+       }
 
        /* clear alarm interrupt if it has occurred */
        if (rtsr & RTSR_AL)
@@ -139,8 +156,58 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static int sa1100_irq_set_freq(struct device *dev, int freq)
+{
+       if (freq < 1 || freq > timer_freq) {
+               return -EINVAL;
+       } else {
+               struct rtc_device *rtc = (struct rtc_device *)dev;
+
+               rtc->irq_freq = freq;
+
+               return 0;
+       }
+}
+
 static int rtc_timer1_count;
 
+static int sa1100_irq_set_state(struct device *dev, int enabled)
+{
+       spin_lock_irq(&sa1100_rtc_lock);
+       if (enabled) {
+               struct rtc_device *rtc = (struct rtc_device *)dev;
+
+               OSMR1 = timer_freq / rtc->irq_freq + OSCR;
+               OIER |= OIER_E1;
+               rtc_timer1_count = 1;
+       } else {
+               OIER &= ~OIER_E1;
+       }
+       spin_unlock_irq(&sa1100_rtc_lock);
+
+       return 0;
+}
+
+static inline int sa1100_timer1_retrigger(struct rtc_device *rtc)
+{
+       unsigned long diff;
+       unsigned long period = timer_freq / rtc->irq_freq;
+
+       spin_lock_irq(&sa1100_rtc_lock);
+
+       do {
+               OSMR1 += period;
+               diff = OSMR1 - OSCR;
+               /* If OSCR > OSMR1, diff is a very large number (unsigned
+                * math). This means we have a lost interrupt. */
+       } while (diff > period);
+       OIER |= OIER_E1;
+
+       spin_unlock_irq(&sa1100_rtc_lock);
+
+       return 0;
+}
+
 static irqreturn_t timer1_interrupt(int irq, void *dev_id)
 {
        struct platform_device *pdev = to_platform_device(dev_id);
@@ -158,7 +225,11 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
        rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
 
        if (rtc_timer1_count == 1)
-               rtc_timer1_count = (rtc_freq * ((1 << 30) / (timer_freq >> 2)));
+               rtc_timer1_count =
+                       (rtc->irq_freq * ((1 << 30) / (timer_freq >> 2)));
+
+       /* retrigger. */
+       sa1100_timer1_retrigger(rtc);
 
        return IRQ_HANDLED;
 }
@@ -166,8 +237,10 @@ static irqreturn_t timer1_interrupt(int irq, void *dev_id)
 static int sa1100_rtc_read_callback(struct device *dev, int data)
 {
        if (data & RTC_PF) {
+               struct rtc_device *rtc = (struct rtc_device *)dev;
+
                /* interpolate missed periods and set match for the next */
-               unsigned long period = timer_freq / rtc_freq;
+               unsigned long period = timer_freq / rtc->irq_freq;
                unsigned long oscr = OSCR;
                unsigned long osmr1 = OSMR1;
                unsigned long missed = (oscr - osmr1)/period;
@@ -178,7 +251,7 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
                 * Here we compare (match - OSCR) 8 instead of 0 --
                 * see comment in pxa_timer_interrupt() for explanation.
                 */
-               while( (signed long)((osmr1 = OSMR1) - OSCR) <= 8 ) {
+               while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) {
                        data += 0x100;
                        OSSR = OSSR_M1; /* clear match on timer 1 */
                        OSMR1 = osmr1 + period;
@@ -190,25 +263,29 @@ static int sa1100_rtc_read_callback(struct device *dev, int data)
 static int sa1100_rtc_open(struct device *dev)
 {
        int ret;
+       struct rtc_device *rtc = (struct rtc_device *)dev;
 
        ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
-                               "rtc 1Hz", dev);
+               "rtc 1Hz", dev);
        if (ret) {
                dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
                goto fail_ui;
        }
        ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
-                               "rtc Alrm", dev);
+               "rtc Alrm", dev);
        if (ret) {
                dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
                goto fail_ai;
        }
        ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
-                               "rtc timer", dev);
+               "rtc timer", dev);
        if (ret) {
                dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
                goto fail_pi;
        }
+       rtc->max_user_freq = RTC_FREQ;
+       sa1100_irq_set_freq(dev, RTC_FREQ);
+
        return 0;
 
  fail_pi:
@@ -236,7 +313,7 @@ static void sa1100_rtc_release(struct device *dev)
 static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
                unsigned long arg)
 {
-       switch(cmd) {
+       switch (cmd) {
        case RTC_AIE_OFF:
                spin_lock_irq(&sa1100_rtc_lock);
                RTSR &= ~RTSR_ALE;
@@ -257,25 +334,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
                RTSR |= RTSR_HZE;
                spin_unlock_irq(&sa1100_rtc_lock);
                return 0;
-       case RTC_PIE_OFF:
-               spin_lock_irq(&sa1100_rtc_lock);
-               OIER &= ~OIER_E1;
-               spin_unlock_irq(&sa1100_rtc_lock);
-               return 0;
-       case RTC_PIE_ON:
-               spin_lock_irq(&sa1100_rtc_lock);
-               OSMR1 = timer_freq / rtc_freq + OSCR;
-               OIER |= OIER_E1;
-               rtc_timer1_count = 1;
-               spin_unlock_irq(&sa1100_rtc_lock);
-               return 0;
-       case RTC_IRQP_READ:
-               return put_user(rtc_freq, (unsigned long *)arg);
-       case RTC_IRQP_SET:
-               if (arg < 1 || arg > timer_freq)
-                       return -EINVAL;
-               rtc_freq = arg;
-               return 0;
        }
        return -ENOIOCTLCMD;
 }
@@ -327,12 +385,15 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
+       struct rtc_device *rtc = (struct rtc_device *)dev;
+
        seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
        seq_printf(seq, "update_IRQ\t: %s\n",
                        (RTSR & RTSR_HZE) ? "yes" : "no");
        seq_printf(seq, "periodic_IRQ\t: %s\n",
                        (OIER & OIER_E1) ? "yes" : "no");
-       seq_printf(seq, "periodic_freq\t: %ld\n", rtc_freq);
+       seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq);
+       seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR);
 
        return 0;
 }
@@ -347,6 +408,8 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
        .read_alarm = sa1100_rtc_read_alarm,
        .set_alarm = sa1100_rtc_set_alarm,
        .proc = sa1100_rtc_proc,
+       .irq_set_freq = sa1100_irq_set_freq,
+       .irq_set_state = sa1100_irq_set_state,
 };
 
 static int sa1100_rtc_probe(struct platform_device *pdev)
@@ -364,7 +427,8 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
         */
        if (RTTR == 0) {
                RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
-               dev_warn(&pdev->dev, "warning: initializing default clock divider/trim value\n");
+               dev_warn(&pdev->dev, "warning: "
+                       "initializing default clock divider/trim value\n");
                /* The current RTC value probably doesn't make sense either */
                RCNR = 0;
        }
@@ -372,13 +436,42 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
        device_init_wakeup(&pdev->dev, 1);
 
        rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
-                               THIS_MODULE);
+               THIS_MODULE);
 
        if (IS_ERR(rtc))
                return PTR_ERR(rtc);
 
        platform_set_drvdata(pdev, rtc);
 
+       /* Set the irq_freq */
+       /*TODO: Find out who is messing with this value after we initialize
+        * it here.*/
+       rtc->irq_freq = RTC_FREQ;
+
+       /* Fix for a nasty initialization problem the in SA11xx RTSR register.
+        * See also the comments in sa1100_rtc_interrupt().
+        *
+        * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
+        * interrupt pending, even though interrupts were never enabled.
+        * In this case, this bit it must be reset before enabling
+        * interruptions to avoid a nonexistent interrupt to occur.
+        *
+        * In principle, the same problem would apply to bit 0, although it has
+        * never been observed to happen.
+        *
+        * This issue is addressed both here and in sa1100_rtc_interrupt().
+        * If the issue is not addressed here, in the times when the processor
+        * wakes up with the bit set there will be one spurious interrupt.
+        *
+        * The issue is also dealt with in sa1100_rtc_interrupt() to be on the
+        * safe side, once the condition that lead to this strange
+        * initialization is unknown and could in principle happen during
+        * normal processing.
+        *
+        * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
+        * the corresponding bits in RTSR. */
+       RTSR = RTSR_AL | RTSR_HZ;
+
        return 0;
 }
 
@@ -386,7 +479,7 @@ static int sa1100_rtc_remove(struct platform_device *pdev)
 {
        struct rtc_device *rtc = platform_get_drvdata(pdev);
 
-       if (rtc)
+       if (rtc)
                rtc_device_unregister(rtc);
 
        return 0;
index c94502dfac664f55fd42080695989d9e1cb1697b..045d7e87b6323e36213d57ee6615c6362f53bab7 100644 (file)
@@ -677,7 +677,7 @@ bfa_fcs_fabric_sm_isolated(struct bfa_fcs_fabric_s *fabric,
        bfa_trc(fabric->fcs, event);
        wwn2str(pwwn_ptr, fabric->bport.port_cfg.pwwn);
 
-       BFA_LOG(KERN_INFO, bfad, log_level,
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Port is isolated due to VF_ID mismatch. "
                "PWWN: %s Port VF_ID: %04x switch port VF_ID: %04x.",
                pwwn_ptr, fabric->fcs->port_vfid,
@@ -1411,7 +1411,7 @@ bfa_fcs_fabric_set_fabric_name(struct bfa_fcs_fabric_s *fabric,
                wwn2str(pwwn_ptr, bfa_fcs_lport_get_pwwn(&fabric->bport));
                wwn2str(fwwn_ptr,
                        bfa_fcs_lport_get_fabric_name(&fabric->bport));
-               BFA_LOG(KERN_WARNING, bfad, log_level,
+               BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
                        "Base port WWN = %s Fabric WWN = %s\n",
                        pwwn_ptr, fwwn_ptr);
        }
index 9662bcdeb41d64c50ab7530fd34ab17d543fc44c..413b58eef93a08088cc7957d63fc9c815d58027c 100644 (file)
@@ -261,7 +261,7 @@ bfa_fcs_itnim_sm_hcb_online(struct bfa_fcs_itnim_s *itnim,
                bfa_fcb_itnim_online(itnim->itnim_drv);
                wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
                wwn2str(rpwwn_buf, itnim->rport->pwwn);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Target (WWN = %s) is online for initiator (WWN = %s)\n",
                rpwwn_buf, lpwwn_buf);
                break;
@@ -301,11 +301,11 @@ bfa_fcs_itnim_sm_online(struct bfa_fcs_itnim_s *itnim,
                wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(itnim->rport->port));
                wwn2str(rpwwn_buf, itnim->rport->pwwn);
                if (bfa_fcs_lport_is_online(itnim->rport->port) == BFA_TRUE)
-                       BFA_LOG(KERN_ERR, bfad, log_level,
+                       BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                        "Target (WWN = %s) connectivity lost for "
                        "initiator (WWN = %s)\n", rpwwn_buf, lpwwn_buf);
                else
-                       BFA_LOG(KERN_INFO, bfad, log_level,
+                       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Target (WWN = %s) offlined by initiator (WWN = %s)\n",
                        rpwwn_buf, lpwwn_buf);
                break;
index 377cbfff6f2ec88a467b6e8014d27c91d3b4a0c3..8d651309302b1f745ef842869ce782d8c9f490b6 100644 (file)
@@ -491,7 +491,7 @@ bfa_fcs_lport_online_actions(struct bfa_fcs_lport_s *port)
        __port_action[port->fabric->fab_type].online(port);
 
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
-       BFA_LOG(KERN_INFO, bfad, log_level,
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Logical port online: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
 
@@ -512,11 +512,11 @@ bfa_fcs_lport_offline_actions(struct bfa_fcs_lport_s *port)
 
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
        if (bfa_fcs_fabric_is_online(port->fabric) == BFA_TRUE)
-               BFA_LOG(KERN_ERR, bfad, log_level,
+               BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                "Logical port lost fabric connectivity: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
        else
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Logical port taken offline: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
 
@@ -573,7 +573,7 @@ bfa_fcs_lport_deleted(struct bfa_fcs_lport_s *port)
        char    lpwwn_buf[BFA_STRING_32];
 
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
-       BFA_LOG(KERN_INFO, bfad, log_level,
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Logical port deleted: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
 
@@ -878,7 +878,7 @@ bfa_fcs_lport_init(struct bfa_fcs_lport_s *lport,
                                        vport ? vport->vport_drv : NULL);
 
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(lport));
-       BFA_LOG(KERN_INFO, bfad, log_level,
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "New logical port created: WWN = %s Role = %s\n",
                lpwwn_buf, "Initiator");
 
index 47f35c0ef29a0c69f5d6842a6db0d173a0195e84..cf4a6e73e60d7dfa5bcaf9b7d94ea986d7389a57 100644 (file)
@@ -2056,7 +2056,7 @@ bfa_fcs_rport_online_action(struct bfa_fcs_rport_s *rport)
        wwn2str(lpwwn_buf, bfa_fcs_lport_get_pwwn(port));
        wwn2str(rpwwn_buf, rport->pwwn);
        if (!BFA_FCS_PID_IS_WKA(rport->pid))
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "Remote port (WWN = %s) online for logical port (WWN = %s)\n",
                rpwwn_buf, lpwwn_buf);
 }
@@ -2075,12 +2075,12 @@ bfa_fcs_rport_offline_action(struct bfa_fcs_rport_s *rport)
        wwn2str(rpwwn_buf, rport->pwwn);
        if (!BFA_FCS_PID_IS_WKA(rport->pid)) {
                if (bfa_fcs_lport_is_online(rport->port) == BFA_TRUE)
-                       BFA_LOG(KERN_ERR, bfad, log_level,
+                       BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "Remote port (WWN = %s) connectivity lost for "
                                "logical port (WWN = %s)\n",
                                rpwwn_buf, lpwwn_buf);
                else
-                       BFA_LOG(KERN_INFO, bfad, log_level,
+                       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "Remote port (WWN = %s) offlined by "
                                "logical port (WWN = %s)\n",
                                rpwwn_buf, lpwwn_buf);
index 54475b53a5ab1494490f2561fdc0c9d7884c0a55..9f4aa391ea9deca5508a0ae90060572ec8a53889 100644 (file)
@@ -402,7 +402,7 @@ bfa_ioc_sm_op_entry(struct bfa_ioc_s *ioc)
 
        ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_OK);
        bfa_ioc_hb_monitor(ioc);
-       BFA_LOG(KERN_INFO, bfad, log_level, "IOC enabled\n");
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC enabled\n");
 }
 
 static void
@@ -444,7 +444,7 @@ bfa_ioc_sm_disabling_entry(struct bfa_ioc_s *ioc)
 {
        struct bfad_s *bfad = (struct bfad_s *)ioc->bfa->bfad;
        bfa_iocpf_disable(ioc);
-       BFA_LOG(KERN_INFO, bfad, log_level, "IOC disabled\n");
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level, "IOC disabled\n");
 }
 
 /*
@@ -565,7 +565,7 @@ bfa_ioc_sm_fail_entry(struct bfa_ioc_s *ioc)
                notify->cbfn(notify->cbarg);
        }
 
-       BFA_LOG(KERN_CRIT, bfad, log_level,
+       BFA_LOG(KERN_CRIT, bfad, bfa_log_level,
                "Heart Beat of IOC has failed\n");
 }
 
@@ -1812,7 +1812,7 @@ bfa_ioc_pf_fwmismatch(struct bfa_ioc_s *ioc)
         * Provide enable completion callback.
         */
        ioc->cbfn->enable_cbfn(ioc->bfa, BFA_STATUS_IOC_FAILURE);
-       BFA_LOG(KERN_WARNING, bfad, log_level,
+       BFA_LOG(KERN_WARNING, bfad, bfa_log_level,
                "Running firmware version is incompatible "
                "with the driver version\n");
 }
index c768143f4805a7cb5f0094682a39c30b73ea433d..37e16ac8f249a33a4045506df74c360d3c5eb698 100644 (file)
@@ -2138,7 +2138,7 @@ bfa_fcport_sm_enabling_qwait(struct bfa_fcport_s *fcport,
                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
                wwn2str(pwwn_buf, fcport->pwwn);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port disabled: WWN = %s\n", pwwn_buf);
                break;
 
@@ -2198,7 +2198,7 @@ bfa_fcport_sm_enabling(struct bfa_fcport_s *fcport,
                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
                wwn2str(pwwn_buf, fcport->pwwn);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port disabled: WWN = %s\n", pwwn_buf);
                break;
 
@@ -2251,7 +2251,7 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
 
                bfa_fcport_scn(fcport, BFA_PORT_LINKUP, BFA_FALSE);
                wwn2str(pwwn_buf, fcport->pwwn);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port online: WWN = %s\n", pwwn_buf);
                break;
 
@@ -2277,7 +2277,7 @@ bfa_fcport_sm_linkdown(struct bfa_fcport_s *fcport,
                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
                wwn2str(pwwn_buf, fcport->pwwn);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port disabled: WWN = %s\n", pwwn_buf);
                break;
 
@@ -2322,9 +2322,9 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                BFA_PL_EID_PORT_DISABLE, 0, "Port Disable");
                wwn2str(pwwn_buf, fcport->pwwn);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port offline: WWN = %s\n", pwwn_buf);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port disabled: WWN = %s\n", pwwn_buf);
                break;
 
@@ -2336,10 +2336,10 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
                                BFA_PL_EID_PORT_ST_CHANGE, 0, "Port Linkdown");
                wwn2str(pwwn_buf, fcport->pwwn);
                if (BFA_PORT_IS_DISABLED(fcport->bfa))
-                       BFA_LOG(KERN_INFO, bfad, log_level,
+                       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "Base port offline: WWN = %s\n", pwwn_buf);
                else
-                       BFA_LOG(KERN_ERR, bfad, log_level,
+                       BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "Base port (WWN = %s) "
                                "lost fabric connectivity\n", pwwn_buf);
                break;
@@ -2349,10 +2349,10 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
                bfa_fcport_reset_linkinfo(fcport);
                wwn2str(pwwn_buf, fcport->pwwn);
                if (BFA_PORT_IS_DISABLED(fcport->bfa))
-                       BFA_LOG(KERN_INFO, bfad, log_level,
+                       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "Base port offline: WWN = %s\n", pwwn_buf);
                else
-                       BFA_LOG(KERN_ERR, bfad, log_level,
+                       BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "Base port (WWN = %s) "
                                "lost fabric connectivity\n", pwwn_buf);
                break;
@@ -2363,10 +2363,10 @@ bfa_fcport_sm_linkup(struct bfa_fcport_s *fcport,
                bfa_fcport_scn(fcport, BFA_PORT_LINKDOWN, BFA_FALSE);
                wwn2str(pwwn_buf, fcport->pwwn);
                if (BFA_PORT_IS_DISABLED(fcport->bfa))
-                       BFA_LOG(KERN_INFO, bfad, log_level,
+                       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "Base port offline: WWN = %s\n", pwwn_buf);
                else
-                       BFA_LOG(KERN_ERR, bfad, log_level,
+                       BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "Base port (WWN = %s) "
                                "lost fabric connectivity\n", pwwn_buf);
                break;
@@ -2497,7 +2497,7 @@ bfa_fcport_sm_disabling(struct bfa_fcport_s *fcport,
                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
                wwn2str(pwwn_buf, fcport->pwwn);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port enabled: WWN = %s\n", pwwn_buf);
                break;
 
@@ -2551,7 +2551,7 @@ bfa_fcport_sm_disabled(struct bfa_fcport_s *fcport,
                bfa_plog_str(fcport->bfa->plog, BFA_PL_MID_HAL,
                                BFA_PL_EID_PORT_ENABLE, 0, "Port Enable");
                wwn2str(pwwn_buf, fcport->pwwn);
-               BFA_LOG(KERN_INFO, bfad, log_level,
+               BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                        "Base port enabled: WWN = %s\n", pwwn_buf);
                break;
 
index 1f938974b84876978600b40d97c265ddd7c2c7c0..6797720213b233bf444937445be983630e60d50d 100644 (file)
@@ -50,7 +50,7 @@ int           reqq_size, rspq_size, num_sgpgs;
 int            rport_del_timeout = BFA_FCS_RPORT_DEF_DEL_TIMEOUT;
 int            bfa_lun_queue_depth = BFAD_LUN_QUEUE_DEPTH;
 int            bfa_io_max_sge = BFAD_IO_MAX_SGE;
-int            log_level = 3; /* WARNING log level */
+int            bfa_log_level = 3; /* WARNING log level */
 int            ioc_auto_recover = BFA_TRUE;
 int            bfa_linkup_delay = -1;
 int            fdmi_enable = BFA_TRUE;
@@ -108,8 +108,8 @@ module_param(bfa_lun_queue_depth, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(bfa_lun_queue_depth, "Lun queue depth, default=32, Range[>0]");
 module_param(bfa_io_max_sge, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(bfa_io_max_sge, "Max io scatter/gather elements, default=255");
-module_param(log_level, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(log_level, "Driver log level, default=3, "
+module_param(bfa_log_level, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(bfa_log_level, "Driver log level, default=3, "
                                "Range[Critical:1|Error:2|Warning:3|Info:4]");
 module_param(ioc_auto_recover, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ioc_auto_recover, "IOC auto recovery, default=1, "
@@ -1112,7 +1112,7 @@ bfad_start_ops(struct bfad_s *bfad) {
        } else
                bfad_os_rport_online_wait(bfad);
 
-       BFA_LOG(KERN_INFO, bfad, log_level, "bfa device claimed\n");
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level, "bfa device claimed\n");
 
        return BFA_STATUS_OK;
 }
index 97f9b6c0937e75cf3a16762092ac46ac6f6cb890..d5ce2349ac59fa5c13c6d3b89d3ec2927561b84c 100644 (file)
@@ -337,7 +337,7 @@ extern int  num_sgpgs;
 extern int      rport_del_timeout;
 extern int      bfa_lun_queue_depth;
 extern int      bfa_io_max_sge;
-extern int      log_level;
+extern int      bfa_log_level;
 extern int      ioc_auto_recover;
 extern int      bfa_linkup_delay;
 extern int      msix_disable_cb;
index 8ca967dee66d4eac1b551c82ff5416454e0ffcb6..fbad5e9b240218bb349ac4c5217e328e785106c3 100644 (file)
@@ -225,7 +225,8 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)
        }
 
        bfa_trc(bfad, hal_io->iotag);
-       BFA_LOG(KERN_INFO, bfad, log_level, "scsi%d: abort cmnd %p iotag %x\n",
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
+               "scsi%d: abort cmnd %p iotag %x\n",
                im_port->shost->host_no, cmnd, hal_io->iotag);
        (void) bfa_ioim_abort(hal_io);
        spin_unlock_irqrestore(&bfad->bfad_lock, flags);
@@ -241,7 +242,7 @@ bfad_im_abort_handler(struct scsi_cmnd *cmnd)
 
        cmnd->scsi_done(cmnd);
        bfa_trc(bfad, hal_io->iotag);
-       BFA_LOG(KERN_INFO, bfad, log_level,
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "scsi%d: complete abort 0x%p iotag 0x%x\n",
                im_port->shost->host_no, cmnd, hal_io->iotag);
        return SUCCESS;
@@ -260,7 +261,7 @@ bfad_im_target_reset_send(struct bfad_s *bfad, struct scsi_cmnd *cmnd,
 
        tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
        if (!tskim) {
-               BFA_LOG(KERN_ERR, bfad, log_level,
+               BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                        "target reset, fail to allocate tskim\n");
                rc = BFA_STATUS_FAILED;
                goto out;
@@ -311,7 +312,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)
 
        tskim = bfa_tskim_alloc(&bfad->bfa, (struct bfad_tskim_s *) cmnd);
        if (!tskim) {
-               BFA_LOG(KERN_ERR, bfad, log_level,
+               BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                "LUN reset, fail to allocate tskim");
                spin_unlock_irqrestore(&bfad->bfad_lock, flags);
                rc = FAILED;
@@ -336,7 +337,7 @@ bfad_im_reset_lun_handler(struct scsi_cmnd *cmnd)
 
        task_status = cmnd->SCp.Status >> 1;
        if (task_status != BFI_TSKIM_STS_OK) {
-               BFA_LOG(KERN_ERR, bfad, log_level,
+               BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                        "LUN reset failure, status: %d\n", task_status);
                rc = FAILED;
        }
@@ -380,7 +381,7 @@ bfad_im_reset_bus_handler(struct scsi_cmnd *cmnd)
 
                        task_status = cmnd->SCp.Status >> 1;
                        if (task_status != BFI_TSKIM_STS_OK) {
-                               BFA_LOG(KERN_ERR, bfad, log_level,
+                               BFA_LOG(KERN_ERR, bfad, bfa_log_level,
                                        "target reset failure,"
                                        " status: %d\n", task_status);
                                err_cnt++;
@@ -460,7 +461,7 @@ bfa_fcb_itnim_free(struct bfad_s *bfad, struct bfad_itnim_s *itnim_drv)
        fcid = bfa_fcs_itnim_get_fcid(&itnim_drv->fcs_itnim);
        wwn2str(wwpn_str, wwpn);
        fcid2str(fcid_str, fcid);
-       BFA_LOG(KERN_INFO, bfad, log_level,
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                "ITNIM FREE scsi%d: FCID: %s WWPN: %s\n",
                port->im_port->shost->host_no,
                fcid_str, wwpn_str);
@@ -589,7 +590,7 @@ void
 bfad_im_scsi_host_free(struct bfad_s *bfad, struct bfad_im_port_s *im_port)
 {
        bfa_trc(bfad, bfad->inst_no);
-       BFA_LOG(KERN_INFO, bfad, log_level, "Free scsi%d\n",
+       BFA_LOG(KERN_INFO, bfad, bfa_log_level, "Free scsi%d\n",
                        im_port->shost->host_no);
 
        fc_remove_host(im_port->shost);
@@ -1048,7 +1049,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)
                        fcid2str(fcid_str, fcid);
                        list_add_tail(&itnim->list_entry,
                                &im_port->itnim_mapped_list);
-                       BFA_LOG(KERN_INFO, bfad, log_level,
+                       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "ITNIM ONLINE Target: %d:0:%d "
                                "FCID: %s WWPN: %s\n",
                                im_port->shost->host_no,
@@ -1081,7 +1082,7 @@ bfad_im_itnim_work_handler(struct work_struct *work)
                        wwn2str(wwpn_str, wwpn);
                        fcid2str(fcid_str, fcid);
                        list_del(&itnim->list_entry);
-                       BFA_LOG(KERN_INFO, bfad, log_level,
+                       BFA_LOG(KERN_INFO, bfad, bfa_log_level,
                                "ITNIM OFFLINE Target: %d:0:%d "
                                "FCID: %s WWPN: %s\n",
                                im_port->shost->host_no,
index 5b6bbaea59fec92565d2af4d708cedce034295ae..4a3842212c5062811c7973413e4d7aec62679951 100644 (file)
@@ -1637,9 +1637,8 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost,
 
        blk_queue_max_segment_size(q, dma_get_max_seg_size(dev));
 
-       /* New queue, no concurrency on queue_flags */
        if (!shost->use_clustering)
-               queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q);
+               q->limits.cluster = 0;
 
        /*
         * set a reasonable default alignment on word boundaries: the
index 6ca7a44f29c205ef37c95318253e2592efaa459b..e76d7d000128f9060a2993c7912cc8e18b70d6c2 100644 (file)
@@ -7,6 +7,7 @@
  *
  *  Copyright 1999 ARM Limited
  *  Copyright (C) 2000 Deep Blue Solutions Ltd.
+ *  Copyright (C) 2010 ST-Ericsson SA
  *
  * 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
@@ -48,6 +49,9 @@
 #include <linux/amba/serial.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/scatterlist.h>
 
 #include <asm/io.h>
 #include <asm/sizes.h>
 #define UART_DR_ERROR          (UART011_DR_OE|UART011_DR_BE|UART011_DR_PE|UART011_DR_FE)
 #define UART_DUMMY_DR_RX       (1 << 16)
 
-/*
- * We wrap our port structure around the generic uart_port.
- */
-struct uart_amba_port {
-       struct uart_port        port;
-       struct clk              *clk;
-       unsigned int            im;             /* interrupt mask */
-       unsigned int            old_status;
-       unsigned int            ifls;           /* vendor-specific */
-       unsigned int            lcrh_tx;        /* vendor-specific */
-       unsigned int            lcrh_rx;        /* vendor-specific */
-       bool                    oversampling;   /* vendor-specific */
-       bool                    autorts;
-};
-
 /* There is by now at least one vendor with differing details, so handle it */
 struct vendor_data {
        unsigned int            ifls;
@@ -85,6 +74,7 @@ struct vendor_data {
        unsigned int            lcrh_tx;
        unsigned int            lcrh_rx;
        bool                    oversampling;
+       bool                    dma_threshold;
 };
 
 static struct vendor_data vendor_arm = {
@@ -93,6 +83,7 @@ static struct vendor_data vendor_arm = {
        .lcrh_tx                = UART011_LCRH,
        .lcrh_rx                = UART011_LCRH,
        .oversampling           = false,
+       .dma_threshold          = false,
 };
 
 static struct vendor_data vendor_st = {
@@ -101,22 +92,535 @@ static struct vendor_data vendor_st = {
        .lcrh_tx                = ST_UART011_LCRH_TX,
        .lcrh_rx                = ST_UART011_LCRH_RX,
        .oversampling           = true,
+       .dma_threshold          = true,
+};
+
+/* Deals with DMA transactions */
+struct pl011_dmatx_data {
+       struct dma_chan         *chan;
+       struct scatterlist      sg;
+       char                    *buf;
+       bool                    queued;
 };
 
+/*
+ * We wrap our port structure around the generic uart_port.
+ */
+struct uart_amba_port {
+       struct uart_port        port;
+       struct clk              *clk;
+       const struct vendor_data *vendor;
+       unsigned int            dmacr;          /* dma control reg */
+       unsigned int            im;             /* interrupt mask */
+       unsigned int            old_status;
+       unsigned int            fifosize;       /* vendor-specific */
+       unsigned int            lcrh_tx;        /* vendor-specific */
+       unsigned int            lcrh_rx;        /* vendor-specific */
+       bool                    autorts;
+       char                    type[12];
+#ifdef CONFIG_DMA_ENGINE
+       /* DMA stuff */
+       bool                    using_dma;
+       struct pl011_dmatx_data dmatx;
+#endif
+};
+
+/*
+ * All the DMA operation mode stuff goes inside this ifdef.
+ * This assumes that you have a generic DMA device interface,
+ * no custom DMA interfaces are supported.
+ */
+#ifdef CONFIG_DMA_ENGINE
+
+#define PL011_DMA_BUFFER_SIZE PAGE_SIZE
+
+static void pl011_dma_probe_initcall(struct uart_amba_port *uap)
+{
+       /* DMA is the sole user of the platform data right now */
+       struct amba_pl011_data *plat = uap->port.dev->platform_data;
+       struct dma_slave_config tx_conf = {
+               .dst_addr = uap->port.mapbase + UART01x_DR,
+               .dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE,
+               .direction = DMA_TO_DEVICE,
+               .dst_maxburst = uap->fifosize >> 1,
+       };
+       struct dma_chan *chan;
+       dma_cap_mask_t mask;
+
+       /* We need platform data */
+       if (!plat || !plat->dma_filter) {
+               dev_info(uap->port.dev, "no DMA platform data\n");
+               return;
+       }
+
+       /* Try to acquire a generic DMA engine slave channel */
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+
+       chan = dma_request_channel(mask, plat->dma_filter, plat->dma_tx_param);
+       if (!chan) {
+               dev_err(uap->port.dev, "no TX DMA channel!\n");
+               return;
+       }
+
+       dmaengine_slave_config(chan, &tx_conf);
+       uap->dmatx.chan = chan;
+
+       dev_info(uap->port.dev, "DMA channel TX %s\n",
+                dma_chan_name(uap->dmatx.chan));
+}
+
+#ifndef MODULE
+/*
+ * Stack up the UARTs and let the above initcall be done at device
+ * initcall time, because the serial driver is called as an arch
+ * initcall, and at this time the DMA subsystem is not yet registered.
+ * At this point the driver will switch over to using DMA where desired.
+ */
+struct dma_uap {
+       struct list_head node;
+       struct uart_amba_port *uap;
+};
+
+static LIST_HEAD(pl011_dma_uarts);
+
+static int __init pl011_dma_initcall(void)
+{
+       struct list_head *node, *tmp;
+
+       list_for_each_safe(node, tmp, &pl011_dma_uarts) {
+               struct dma_uap *dmau = list_entry(node, struct dma_uap, node);
+               pl011_dma_probe_initcall(dmau->uap);
+               list_del(node);
+               kfree(dmau);
+       }
+       return 0;
+}
+
+device_initcall(pl011_dma_initcall);
+
+static void pl011_dma_probe(struct uart_amba_port *uap)
+{
+       struct dma_uap *dmau = kzalloc(sizeof(struct dma_uap), GFP_KERNEL);
+       if (dmau) {
+               dmau->uap = uap;
+               list_add_tail(&dmau->node, &pl011_dma_uarts);
+       }
+}
+#else
+static void pl011_dma_probe(struct uart_amba_port *uap)
+{
+       pl011_dma_probe_initcall(uap);
+}
+#endif
+
+static void pl011_dma_remove(struct uart_amba_port *uap)
+{
+       /* TODO: remove the initcall if it has not yet executed */
+       if (uap->dmatx.chan)
+               dma_release_channel(uap->dmatx.chan);
+}
+
+
+/* Forward declare this for the refill routine */
+static int pl011_dma_tx_refill(struct uart_amba_port *uap);
+
+/*
+ * The current DMA TX buffer has been sent.
+ * Try to queue up another DMA buffer.
+ */
+static void pl011_dma_tx_callback(void *data)
+{
+       struct uart_amba_port *uap = data;
+       struct pl011_dmatx_data *dmatx = &uap->dmatx;
+       unsigned long flags;
+       u16 dmacr;
+
+       spin_lock_irqsave(&uap->port.lock, flags);
+       if (uap->dmatx.queued)
+               dma_unmap_sg(dmatx->chan->device->dev, &dmatx->sg, 1,
+                            DMA_TO_DEVICE);
+
+       dmacr = uap->dmacr;
+       uap->dmacr = dmacr & ~UART011_TXDMAE;
+       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+
+       /*
+        * If TX DMA was disabled, it means that we've stopped the DMA for
+        * some reason (eg, XOFF received, or we want to send an X-char.)
+        *
+        * Note: we need to be careful here of a potential race between DMA
+        * and the rest of the driver - if the driver disables TX DMA while
+        * a TX buffer completing, we must update the tx queued status to
+        * get further refills (hence we check dmacr).
+        */
+       if (!(dmacr & UART011_TXDMAE) || uart_tx_stopped(&uap->port) ||
+           uart_circ_empty(&uap->port.state->xmit)) {
+               uap->dmatx.queued = false;
+               spin_unlock_irqrestore(&uap->port.lock, flags);
+               return;
+       }
+
+       if (pl011_dma_tx_refill(uap) <= 0) {
+               /*
+                * We didn't queue a DMA buffer for some reason, but we
+                * have data pending to be sent.  Re-enable the TX IRQ.
+                */
+               uap->im |= UART011_TXIM;
+               writew(uap->im, uap->port.membase + UART011_IMSC);
+       }
+       spin_unlock_irqrestore(&uap->port.lock, flags);
+}
+
+/*
+ * Try to refill the TX DMA buffer.
+ * Locking: called with port lock held and IRQs disabled.
+ * Returns:
+ *   1 if we queued up a TX DMA buffer.
+ *   0 if we didn't want to handle this by DMA
+ *  <0 on error
+ */
+static int pl011_dma_tx_refill(struct uart_amba_port *uap)
+{
+       struct pl011_dmatx_data *dmatx = &uap->dmatx;
+       struct dma_chan *chan = dmatx->chan;
+       struct dma_device *dma_dev = chan->device;
+       struct dma_async_tx_descriptor *desc;
+       struct circ_buf *xmit = &uap->port.state->xmit;
+       unsigned int count;
+
+       /*
+        * Try to avoid the overhead involved in using DMA if the
+        * transaction fits in the first half of the FIFO, by using
+        * the standard interrupt handling.  This ensures that we
+        * issue a uart_write_wakeup() at the appropriate time.
+        */
+       count = uart_circ_chars_pending(xmit);
+       if (count < (uap->fifosize >> 1)) {
+               uap->dmatx.queued = false;
+               return 0;
+       }
+
+       /*
+        * Bodge: don't send the last character by DMA, as this
+        * will prevent XON from notifying us to restart DMA.
+        */
+       count -= 1;
+
+       /* Else proceed to copy the TX chars to the DMA buffer and fire DMA */
+       if (count > PL011_DMA_BUFFER_SIZE)
+               count = PL011_DMA_BUFFER_SIZE;
+
+       if (xmit->tail < xmit->head)
+               memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], count);
+       else {
+               size_t first = UART_XMIT_SIZE - xmit->tail;
+               size_t second = xmit->head;
+
+               memcpy(&dmatx->buf[0], &xmit->buf[xmit->tail], first);
+               if (second)
+                       memcpy(&dmatx->buf[first], &xmit->buf[0], second);
+       }
+
+       dmatx->sg.length = count;
+
+       if (dma_map_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE) != 1) {
+               uap->dmatx.queued = false;
+               dev_dbg(uap->port.dev, "unable to map TX DMA\n");
+               return -EBUSY;
+       }
+
+       desc = dma_dev->device_prep_slave_sg(chan, &dmatx->sg, 1, DMA_TO_DEVICE,
+                                            DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+       if (!desc) {
+               dma_unmap_sg(dma_dev->dev, &dmatx->sg, 1, DMA_TO_DEVICE);
+               uap->dmatx.queued = false;
+               /*
+                * If DMA cannot be used right now, we complete this
+                * transaction via IRQ and let the TTY layer retry.
+                */
+               dev_dbg(uap->port.dev, "TX DMA busy\n");
+               return -EBUSY;
+       }
+
+       /* Some data to go along to the callback */
+       desc->callback = pl011_dma_tx_callback;
+       desc->callback_param = uap;
+
+       /* All errors should happen at prepare time */
+       dmaengine_submit(desc);
+
+       /* Fire the DMA transaction */
+       dma_dev->device_issue_pending(chan);
+
+       uap->dmacr |= UART011_TXDMAE;
+       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       uap->dmatx.queued = true;
+
+       /*
+        * Now we know that DMA will fire, so advance the ring buffer
+        * with the stuff we just dispatched.
+        */
+       xmit->tail = (xmit->tail + count) & (UART_XMIT_SIZE - 1);
+       uap->port.icount.tx += count;
+
+       if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+               uart_write_wakeup(&uap->port);
+
+       return 1;
+}
+
+/*
+ * We received a transmit interrupt without a pending X-char but with
+ * pending characters.
+ * Locking: called with port lock held and IRQs disabled.
+ * Returns:
+ *   false if we want to use PIO to transmit
+ *   true if we queued a DMA buffer
+ */
+static bool pl011_dma_tx_irq(struct uart_amba_port *uap)
+{
+       if (!uap->using_dma)
+               return false;
+
+       /*
+        * If we already have a TX buffer queued, but received a
+        * TX interrupt, it will be because we've just sent an X-char.
+        * Ensure the TX DMA is enabled and the TX IRQ is disabled.
+        */
+       if (uap->dmatx.queued) {
+               uap->dmacr |= UART011_TXDMAE;
+               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+               uap->im &= ~UART011_TXIM;
+               writew(uap->im, uap->port.membase + UART011_IMSC);
+               return true;
+       }
+
+       /*
+        * We don't have a TX buffer queued, so try to queue one.
+        * If we succesfully queued a buffer, mask the TX IRQ.
+        */
+       if (pl011_dma_tx_refill(uap) > 0) {
+               uap->im &= ~UART011_TXIM;
+               writew(uap->im, uap->port.membase + UART011_IMSC);
+               return true;
+       }
+       return false;
+}
+
+/*
+ * Stop the DMA transmit (eg, due to received XOFF).
+ * Locking: called with port lock held and IRQs disabled.
+ */
+static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
+{
+       if (uap->dmatx.queued) {
+               uap->dmacr &= ~UART011_TXDMAE;
+               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       }
+}
+
+/*
+ * Try to start a DMA transmit, or in the case of an XON/OFF
+ * character queued for send, try to get that character out ASAP.
+ * Locking: called with port lock held and IRQs disabled.
+ * Returns:
+ *   false if we want the TX IRQ to be enabled
+ *   true if we have a buffer queued
+ */
+static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
+{
+       u16 dmacr;
+
+       if (!uap->using_dma)
+               return false;
+
+       if (!uap->port.x_char) {
+               /* no X-char, try to push chars out in DMA mode */
+               bool ret = true;
+
+               if (!uap->dmatx.queued) {
+                       if (pl011_dma_tx_refill(uap) > 0) {
+                               uap->im &= ~UART011_TXIM;
+                               ret = true;
+                       } else {
+                               uap->im |= UART011_TXIM;
+                               ret = false;
+                       }
+                       writew(uap->im, uap->port.membase + UART011_IMSC);
+               } else if (!(uap->dmacr & UART011_TXDMAE)) {
+                       uap->dmacr |= UART011_TXDMAE;
+                       writew(uap->dmacr,
+                                      uap->port.membase + UART011_DMACR);
+               }
+               return ret;
+       }
+
+       /*
+        * We have an X-char to send.  Disable DMA to prevent it loading
+        * the TX fifo, and then see if we can stuff it into the FIFO.
+        */
+       dmacr = uap->dmacr;
+       uap->dmacr &= ~UART011_TXDMAE;
+       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+
+       if (readw(uap->port.membase + UART01x_FR) & UART01x_FR_TXFF) {
+               /*
+                * No space in the FIFO, so enable the transmit interrupt
+                * so we know when there is space.  Note that once we've
+                * loaded the character, we should just re-enable DMA.
+                */
+               return false;
+       }
+
+       writew(uap->port.x_char, uap->port.membase + UART01x_DR);
+       uap->port.icount.tx++;
+       uap->port.x_char = 0;
+
+       /* Success - restore the DMA state */
+       uap->dmacr = dmacr;
+       writew(dmacr, uap->port.membase + UART011_DMACR);
+
+       return true;
+}
+
+/*
+ * Flush the transmit buffer.
+ * Locking: called with port lock held and IRQs disabled.
+ */
+static void pl011_dma_flush_buffer(struct uart_port *port)
+{
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
+
+       if (!uap->using_dma)
+               return;
+
+       /* Avoid deadlock with the DMA engine callback */
+       spin_unlock(&uap->port.lock);
+       dmaengine_terminate_all(uap->dmatx.chan);
+       spin_lock(&uap->port.lock);
+       if (uap->dmatx.queued) {
+               dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
+                            DMA_TO_DEVICE);
+               uap->dmatx.queued = false;
+               uap->dmacr &= ~UART011_TXDMAE;
+               writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       }
+}
+
+
+static void pl011_dma_startup(struct uart_amba_port *uap)
+{
+       if (!uap->dmatx.chan)
+               return;
+
+       uap->dmatx.buf = kmalloc(PL011_DMA_BUFFER_SIZE, GFP_KERNEL);
+       if (!uap->dmatx.buf) {
+               dev_err(uap->port.dev, "no memory for DMA TX buffer\n");
+               uap->port.fifosize = uap->fifosize;
+               return;
+       }
+
+       sg_init_one(&uap->dmatx.sg, uap->dmatx.buf, PL011_DMA_BUFFER_SIZE);
+
+       /* The DMA buffer is now the FIFO the TTY subsystem can use */
+       uap->port.fifosize = PL011_DMA_BUFFER_SIZE;
+       uap->using_dma = true;
+
+       /* Turn on DMA error (RX/TX will be enabled on demand) */
+       uap->dmacr |= UART011_DMAONERR;
+       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+
+       /*
+        * ST Micro variants has some specific dma burst threshold
+        * compensation. Set this to 16 bytes, so burst will only
+        * be issued above/below 16 bytes.
+        */
+       if (uap->vendor->dma_threshold)
+               writew(ST_UART011_DMAWM_RX_16 | ST_UART011_DMAWM_TX_16,
+                              uap->port.membase + ST_UART011_DMAWM);
+}
+
+static void pl011_dma_shutdown(struct uart_amba_port *uap)
+{
+       if (!uap->using_dma)
+               return;
+
+       /* Disable RX and TX DMA */
+       while (readw(uap->port.membase + UART01x_FR) & UART01x_FR_BUSY)
+               barrier();
+
+       spin_lock_irq(&uap->port.lock);
+       uap->dmacr &= ~(UART011_DMAONERR | UART011_RXDMAE | UART011_TXDMAE);
+       writew(uap->dmacr, uap->port.membase + UART011_DMACR);
+       spin_unlock_irq(&uap->port.lock);
+
+       /* In theory, this should already be done by pl011_dma_flush_buffer */
+       dmaengine_terminate_all(uap->dmatx.chan);
+       if (uap->dmatx.queued) {
+               dma_unmap_sg(uap->dmatx.chan->device->dev, &uap->dmatx.sg, 1,
+                            DMA_TO_DEVICE);
+               uap->dmatx.queued = false;
+       }
+
+       kfree(uap->dmatx.buf);
+
+       uap->using_dma = false;
+}
+
+#else
+/* Blank functions if the DMA engine is not available */
+static inline void pl011_dma_probe(struct uart_amba_port *uap)
+{
+}
+
+static inline void pl011_dma_remove(struct uart_amba_port *uap)
+{
+}
+
+static inline void pl011_dma_startup(struct uart_amba_port *uap)
+{
+}
+
+static inline void pl011_dma_shutdown(struct uart_amba_port *uap)
+{
+}
+
+static inline bool pl011_dma_tx_irq(struct uart_amba_port *uap)
+{
+       return false;
+}
+
+static inline void pl011_dma_tx_stop(struct uart_amba_port *uap)
+{
+}
+
+static inline bool pl011_dma_tx_start(struct uart_amba_port *uap)
+{
+       return false;
+}
+
+#define pl011_dma_flush_buffer NULL
+#endif
+
+
 static void pl011_stop_tx(struct uart_port *port)
 {
        struct uart_amba_port *uap = (struct uart_amba_port *)port;
 
        uap->im &= ~UART011_TXIM;
        writew(uap->im, uap->port.membase + UART011_IMSC);
+       pl011_dma_tx_stop(uap);
 }
 
 static void pl011_start_tx(struct uart_port *port)
 {
        struct uart_amba_port *uap = (struct uart_amba_port *)port;
 
-       uap->im |= UART011_TXIM;
-       writew(uap->im, uap->port.membase + UART011_IMSC);
+       if (!pl011_dma_tx_start(uap)) {
+               uap->im |= UART011_TXIM;
+               writew(uap->im, uap->port.membase + UART011_IMSC);
+       }
 }
 
 static void pl011_stop_rx(struct uart_port *port)
@@ -203,7 +707,11 @@ static void pl011_tx_chars(struct uart_amba_port *uap)
                return;
        }
 
-       count = uap->port.fifosize >> 1;
+       /* If we are using DMA mode, try to send some characters. */
+       if (pl011_dma_tx_irq(uap))
+               return;
+
+       count = uap->fifosize >> 1;
        do {
                writew(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR);
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
@@ -246,10 +754,11 @@ static void pl011_modem_status(struct uart_amba_port *uap)
 static irqreturn_t pl011_int(int irq, void *dev_id)
 {
        struct uart_amba_port *uap = dev_id;
+       unsigned long flags;
        unsigned int status, pass_counter = AMBA_ISR_PASS_LIMIT;
        int handled = 0;
 
-       spin_lock(&uap->port.lock);
+       spin_lock_irqsave(&uap->port.lock, flags);
 
        status = readw(uap->port.membase + UART011_MIS);
        if (status) {
@@ -274,7 +783,7 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
                handled = 1;
        }
 
-       spin_unlock(&uap->port.lock);
+       spin_unlock_irqrestore(&uap->port.lock, flags);
 
        return IRQ_RETVAL(handled);
 }
@@ -396,7 +905,7 @@ static int pl011_startup(struct uart_port *port)
        if (retval)
                goto clk_dis;
 
-       writew(uap->ifls, uap->port.membase + UART011_IFLS);
+       writew(uap->vendor->ifls, uap->port.membase + UART011_IFLS);
 
        /*
         * Provoke TX FIFO interrupt into asserting.
@@ -423,11 +932,18 @@ static int pl011_startup(struct uart_port *port)
        cr = UART01x_CR_UARTEN | UART011_CR_RXE | UART011_CR_TXE;
        writew(cr, uap->port.membase + UART011_CR);
 
+       /* Clear pending error interrupts */
+       writew(UART011_OEIS | UART011_BEIS | UART011_PEIS | UART011_FEIS,
+              uap->port.membase + UART011_ICR);
+
        /*
         * initialise the old status of the modem signals
         */
        uap->old_status = readw(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY;
 
+       /* Startup DMA */
+       pl011_dma_startup(uap);
+
        /*
         * Finally, enable interrupts
         */
@@ -467,6 +983,8 @@ static void pl011_shutdown(struct uart_port *port)
        writew(0xffff, uap->port.membase + UART011_ICR);
        spin_unlock_irq(&uap->port.lock);
 
+       pl011_dma_shutdown(uap);
+
        /*
         * Free the interrupt
         */
@@ -498,13 +1016,18 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
        struct uart_amba_port *uap = (struct uart_amba_port *)port;
        unsigned int lcr_h, old_cr;
        unsigned long flags;
-       unsigned int baud, quot;
+       unsigned int baud, quot, clkdiv;
+
+       if (uap->vendor->oversampling)
+               clkdiv = 8;
+       else
+               clkdiv = 16;
 
        /*
         * Ask the core to calculate the divisor for us.
         */
        baud = uart_get_baud_rate(port, termios, old, 0,
-                                 port->uartclk/(uap->oversampling ? 8 : 16));
+                                 port->uartclk / clkdiv);
 
        if (baud > port->uartclk/16)
                quot = DIV_ROUND_CLOSEST(port->uartclk * 8, baud);
@@ -532,7 +1055,7 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
                if (!(termios->c_cflag & PARODD))
                        lcr_h |= UART01x_LCRH_EPS;
        }
-       if (port->fifosize > 1)
+       if (uap->fifosize > 1)
                lcr_h |= UART01x_LCRH_FEN;
 
        spin_lock_irqsave(&port->lock, flags);
@@ -588,8 +1111,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
                uap->autorts = false;
        }
 
-       if (uap->oversampling) {
-               if (baud > port->uartclk/16)
+       if (uap->vendor->oversampling) {
+               if (baud > port->uartclk / 16)
                        old_cr |= ST_UART011_CR_OVSFACT;
                else
                        old_cr &= ~ST_UART011_CR_OVSFACT;
@@ -622,7 +1145,8 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios,
 
 static const char *pl011_type(struct uart_port *port)
 {
-       return port->type == PORT_AMBA ? "AMBA/PL011" : NULL;
+       struct uart_amba_port *uap = (struct uart_amba_port *)port;
+       return uap->port.type == PORT_AMBA ? uap->type : NULL;
 }
 
 /*
@@ -679,6 +1203,7 @@ static struct uart_ops amba_pl011_pops = {
        .break_ctl      = pl011_break_ctl,
        .startup        = pl011_startup,
        .shutdown       = pl011_shutdown,
+       .flush_buffer   = pl011_dma_flush_buffer,
        .set_termios    = pl011_set_termios,
        .type           = pl011_type,
        .release_port   = pl010_release_port,
@@ -761,7 +1286,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
 
                *baud = uap->port.uartclk * 4 / (64 * ibrd + fbrd);
 
-               if (uap->oversampling) {
+               if (uap->vendor->oversampling) {
                        if (readw(uap->port.membase + UART011_CR)
                                  & ST_UART011_CR_OVSFACT)
                                *baud *= 2;
@@ -858,19 +1383,22 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id)
                goto unmap;
        }
 
-       uap->ifls = vendor->ifls;
+       uap->vendor = vendor;
        uap->lcrh_rx = vendor->lcrh_rx;
        uap->lcrh_tx = vendor->lcrh_tx;
-       uap->oversampling = vendor->oversampling;
+       uap->fifosize = vendor->fifosize;
        uap->port.dev = &dev->dev;
        uap->port.mapbase = dev->res.start;
        uap->port.membase = base;
        uap->port.iotype = UPIO_MEM;
        uap->port.irq = dev->irq[0];
-       uap->port.fifosize = vendor->fifosize;
+       uap->port.fifosize = uap->fifosize;
        uap->port.ops = &amba_pl011_pops;
        uap->port.flags = UPF_BOOT_AUTOCONF;
        uap->port.line = i;
+       pl011_dma_probe(uap);
+
+       snprintf(uap->type, sizeof(uap->type), "PL011 rev%u", amba_rev(dev));
 
        amba_ports[i] = uap;
 
@@ -879,6 +1407,7 @@ static int pl011_probe(struct amba_device *dev, struct amba_id *id)
        if (ret) {
                amba_set_drvdata(dev, NULL);
                amba_ports[i] = NULL;
+               pl011_dma_remove(uap);
                clk_put(uap->clk);
  unmap:
                iounmap(base);
@@ -902,6 +1431,7 @@ static int pl011_remove(struct amba_device *dev)
                if (amba_ports[i] == uap)
                        amba_ports[i] = NULL;
 
+       pl011_dma_remove(uap);
        iounmap(uap->port.membase);
        clk_put(uap->clk);
        kfree(uap);
index e5e9e6735f7d62e3d585505de7be4fe379fbbd40..9739431092d126aefdef78ec03888c66b40b256d 100644 (file)
@@ -198,6 +198,7 @@ int __init register_intc_controller(struct intc_desc *desc)
        list_add_tail(&d->list, &intc_list);
 
        raw_spin_lock_init(&d->lock);
+       INIT_RADIX_TREE(&d->tree, GFP_ATOMIC);
 
        d->index = nr_intc_controllers;
 
index 052b3c7fa6a0f644d26c613e67e69ffe00ad05be..8856bcca9d2933db4a8f98526bc716c6640bb075 100644 (file)
@@ -317,7 +317,7 @@ static void mcfqspi_work(struct work_struct *work)
                msg = container_of(mcfqspi->msgq.next, struct spi_message,
                                   queue);
 
-               list_del_init(&mcfqspi->msgq);
+               list_del_init(&msg->queue);
                spin_unlock_irqrestore(&mcfqspi->lock, flags);
 
                spi = msg->spi;
index ec9f0b1bf86494da73bd8d14cc69fe5927db8065..84439f655601f71577483acd423aed7622fae807 100644 (file)
@@ -563,7 +563,7 @@ static struct of_platform_driver mpc52xx_spi_of_driver = {
                .of_match_table = mpc52xx_spi_match,
        },
        .probe = mpc52xx_spi_probe,
-       .remove = __exit_p(mpc52xx_spi_remove),
+       .remove = __devexit_p(mpc52xx_spi_remove),
 };
 
 static int __init mpc52xx_spi_init(void)
index 2a651e61bfbff30f23e8e44dddfcb70ab8a05173..951a160fc27fbe2614376776ba3b712646e305ff 100644 (file)
@@ -1305,10 +1305,49 @@ static int __exit omap2_mcspi_remove(struct platform_device *pdev)
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:omap2_mcspi");
 
+#ifdef CONFIG_SUSPEND
+/*
+ * When SPI wake up from off-mode, CS is in activate state. If it was in
+ * unactive state when driver was suspend, then force it to unactive state at
+ * wake up.
+ */
+static int omap2_mcspi_resume(struct device *dev)
+{
+       struct spi_master       *master = dev_get_drvdata(dev);
+       struct omap2_mcspi      *mcspi = spi_master_get_devdata(master);
+       struct omap2_mcspi_cs *cs;
+
+       omap2_mcspi_enable_clocks(mcspi);
+       list_for_each_entry(cs, &omap2_mcspi_ctx[master->bus_num - 1].cs,
+                           node) {
+               if ((cs->chconf0 & OMAP2_MCSPI_CHCONF_FORCE) == 0) {
+
+                       /*
+                        * We need to toggle CS state for OMAP take this
+                        * change in account.
+                        */
+                       MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 1);
+                       __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+                       MOD_REG_BIT(cs->chconf0, OMAP2_MCSPI_CHCONF_FORCE, 0);
+                       __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0);
+               }
+       }
+       omap2_mcspi_disable_clocks(mcspi);
+       return 0;
+}
+#else
+#define        omap2_mcspi_resume      NULL
+#endif
+
+static const struct dev_pm_ops omap2_mcspi_pm_ops = {
+       .resume = omap2_mcspi_resume,
+};
+
 static struct platform_driver omap2_mcspi_driver = {
        .driver = {
                .name =         "omap2_mcspi",
                .owner =        THIS_MODULE,
+               .pm =           &omap2_mcspi_pm_ops
        },
        .remove =       __exit_p(omap2_mcspi_remove),
 };
index 709c836607de23636e6c567a38833cceff752b08..b02d0cbce89049e003fe8300421adeed847e92ce 100644 (file)
@@ -584,8 +584,7 @@ void spi_unregister_master(struct spi_master *master)
        list_del(&master->list);
        mutex_unlock(&board_lock);
 
-       dummy = device_for_each_child(master->dev.parent, &master->dev,
-                                       __unregister);
+       dummy = device_for_each_child(&master->dev, NULL, __unregister);
        device_unregister(&master->dev);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_master);
index e3b4f645196603e517e22ef782205a02fb224b22..a99e2333b949efdbc10e391253ae952137238b7d 100644 (file)
@@ -258,18 +258,18 @@ static int fsl_espi_bufs(struct spi_device *spi, struct spi_transfer *t)
        return mpc8xxx_spi->count;
 }
 
-static void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
+static inline void fsl_espi_addr2cmd(unsigned int addr, u8 *cmd)
 {
-       if (cmd[1] && cmd[2] && cmd[3]) {
+       if (cmd) {
                cmd[1] = (u8)(addr >> 16);
                cmd[2] = (u8)(addr >> 8);
                cmd[3] = (u8)(addr >> 0);
        }
 }
 
-static unsigned int fsl_espi_cmd2addr(u8 *cmd)
+static inline unsigned int fsl_espi_cmd2addr(u8 *cmd)
 {
-       if (cmd[1] && cmd[2] && cmd[3])
+       if (cmd)
                return cmd[1] << 16 | cmd[2] << 8 | cmd[3] << 0;
 
        return 0;
@@ -395,9 +395,11 @@ static void fsl_espi_rw_trans(struct spi_message *m,
                        }
                }
 
-               addr = fsl_espi_cmd2addr(local_buf);
-               addr += pos;
-               fsl_espi_addr2cmd(addr, local_buf);
+               if (pos > 0) {
+                       addr = fsl_espi_cmd2addr(local_buf);
+                       addr += pos;
+                       fsl_espi_addr2cmd(addr, local_buf);
+               }
 
                espi_trans->n_tx = n_tx;
                espi_trans->n_rx = trans_len;
@@ -507,16 +509,29 @@ void fsl_espi_cpu_irq(struct mpc8xxx_spi *mspi, u32 events)
 
        /* We need handle RX first */
        if (events & SPIE_NE) {
-               u32 rx_data;
+               u32 rx_data, tmp;
+               u8 rx_data_8;
 
                /* Spin until RX is done */
                while (SPIE_RXCNT(events) < min(4, mspi->len)) {
                        cpu_relax();
                        events = mpc8xxx_spi_read_reg(&reg_base->event);
                }
-               mspi->len -= 4;
 
-               rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
+               if (mspi->len >= 4) {
+                       rx_data = mpc8xxx_spi_read_reg(&reg_base->receive);
+               } else {
+                       tmp = mspi->len;
+                       rx_data = 0;
+                       while (tmp--) {
+                               rx_data_8 = in_8((u8 *)&reg_base->receive);
+                               rx_data |= (rx_data_8 << (tmp * 8));
+                       }
+
+                       rx_data <<= (4 - mspi->len) * 8;
+               }
+
+               mspi->len -= 4;
 
                if (mspi->rx)
                        mspi->get_rx(rx_data, mspi);
index e7f1d5778cec3f7b4044d5675caddfb0ecd10f54..52389308f3337ebb84daa31490f496b8057548ba 100644 (file)
@@ -92,7 +92,7 @@ int cx25821_get_format_size(void)
        return ARRAY_SIZE(formats);
 }
 
-struct cx25821_fmt *format_by_fourcc(unsigned int fourcc)
+struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc)
 {
        unsigned int i;
 
@@ -848,7 +848,7 @@ static int video_open(struct file *file)
        pix_format =
           (dev->channels[ch_id].pixel_formats ==
            PIXEL_FRMT_411) ? V4L2_PIX_FMT_Y41P : V4L2_PIX_FMT_YUYV;
-       fh->fmt = format_by_fourcc(pix_format);
+       fh->fmt = cx25821_format_by_fourcc(pix_format);
 
        v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio);
 
@@ -1010,7 +1010,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        if (0 != err)
               return err;
 
-       fh->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
        fh->vidq.field = f->fmt.pix.field;
 
        /* check if width and height is valid based on set standard */
@@ -1119,7 +1119,7 @@ int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fo
        enum v4l2_field field;
        unsigned int maxw, maxh;
 
-       fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+       fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat);
        if (NULL == fmt)
                return -EINVAL;
 
index cc6034b1a95d717ca632c1e95a70d49307449c45..a2415d33235b2b41a62a5230822a62250589e6b1 100644 (file)
@@ -87,7 +87,7 @@ extern unsigned int vid_limit;
 
 #define FORMAT_FLAGS_PACKED       0x01
 extern struct cx25821_fmt formats[];
-extern struct cx25821_fmt *format_by_fourcc(unsigned int fourcc);
+extern struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc);
 extern struct cx25821_data timeout_data[MAX_VID_CHANNEL_NUM];
 
 extern void cx25821_dump_video_queue(struct cx25821_dev *dev,
index 8c3c057aa8478fb2a436edfd571843513544ca71..d0e9e0207539e2c9491fc6c1de25c75dda4bd9c6 100644 (file)
@@ -435,12 +435,6 @@ static int zram_make_request(struct request_queue *queue, struct bio *bio)
        int ret = 0;
        struct zram *zram = queue->queuedata;
 
-       if (unlikely(!zram->init_done)) {
-               set_bit(BIO_UPTODATE, &bio->bi_flags);
-               bio_endio(bio, 0);
-               return 0;
-       }
-
        if (!valid_io_request(zram, bio)) {
                zram_stat64_inc(zram, &zram->stats.invalid_io);
                bio_io_error(bio);
index 81b46585edf797561828f2adfac2e598543690f3..c5f8e5bda2b29c4606f3245ba9388f943d3f2147 100644 (file)
@@ -716,8 +716,8 @@ static void __gsm_data_queue(struct gsm_dlci *dlci, struct gsm_msg *msg)
                if (msg->len < 128)
                        *--dp = (msg->len << 1) | EA;
                else {
-                       *--dp = ((msg->len & 127) << 1) | EA;
-                       *--dp = (msg->len >> 6) & 0xfe;
+                       *--dp = (msg->len >> 7);        /* bits 7 - 15 */
+                       *--dp = (msg->len & 127) << 1;  /* bits 0 - 6 */
                }
        }
 
@@ -968,6 +968,8 @@ static void gsm_control_reply(struct gsm_mux *gsm, int cmd, u8 *data,
 {
        struct gsm_msg *msg;
        msg = gsm_data_alloc(gsm, 0, dlen + 2, gsm->ftype);
+       if (msg == NULL)
+               return;
        msg->data[0] = (cmd & 0xFE) << 1 | EA;  /* Clear C/R */
        msg->data[1] = (dlen << 1) | EA;
        memcpy(msg->data + 2, data, dlen);
index 44447f54942f6d6e1c7c7e2a777b4c882f6b546d..99ac70e32556f841b83c909108767dedf444237e 100644 (file)
@@ -2206,8 +2206,11 @@ static int uea_boot(struct uea_softc *sc)
                goto err1;
        }
 
-       sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
-       if (sc->kthread == ERR_PTR(-ENOMEM)) {
+       /* Create worker thread, but don't start it here.  Start it after
+        * all usbatm generic initialization is done.
+        */
+       sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
+       if (IS_ERR(sc->kthread)) {
                uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
                goto err2;
        }
@@ -2624,6 +2627,7 @@ static struct usbatm_driver uea_usbatm_driver = {
 static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        struct usb_device *usb = interface_to_usbdev(intf);
+       int ret;
 
        uea_enters(usb);
        uea_info(usb, "ADSL device founded vid (%#X) pid (%#X) Rev (%#X): %s\n",
@@ -2637,7 +2641,19 @@ static int uea_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (UEA_IS_PREFIRM(id))
                return uea_load_firmware(usb, UEA_CHIP_VERSION(id));
 
-       return usbatm_usb_probe(intf, id, &uea_usbatm_driver);
+       ret = usbatm_usb_probe(intf, id, &uea_usbatm_driver);
+       if (ret == 0) {
+               struct usbatm_data *usbatm = usb_get_intfdata(intf);
+               struct uea_softc *sc = usbatm->driver_data;
+
+               /* Ensure carrier is initialized to off as early as possible */
+               UPDATE_ATM_SIGNAL(ATM_PHY_SIG_LOST);
+
+               /* Only start the worker thread when all init is done */
+               wake_up_process(sc->kthread);
+       }
+
+       return ret;
 }
 
 static void uea_disconnect(struct usb_interface *intf)
index 9eed5b52d9de22647f6ca7e94791cd97f6e60122..bcc24779ba0e3145f713dd7bf6c0f73368763de3 100644 (file)
@@ -107,11 +107,19 @@ config USB_SUSPEND
          If you are unsure about this, say N here.
 
 config USB_OTG
-       bool
+       bool "OTG support"
        depends on USB && EXPERIMENTAL
        depends on USB_SUSPEND
        default n
-
+       help
+         The most notable feature of USB OTG is support for a
+         "Dual-Role" device, which can act as either a device
+         or a host. The initial role is decided by the type of
+         plug inserted and can be changed later when two dual
+         role devices talk to each other.
+
+         Select this only if your board has Mini-AB/Micro-AB
+         connector.
 
 config USB_OTG_WHITELIST
        bool "Rely on OTG Targeted Peripherals List"
index 7b5cc16e4a0bbc4b61e0627df7bee1479fbda2f4..8572dad5ecbbffd0e0eb71ece46559b30ca6f796 100644 (file)
@@ -1047,9 +1047,9 @@ composite_unbind(struct usb_gadget *gadget)
                kfree(cdev->req->buf);
                usb_ep_free_request(gadget->ep0, cdev->req);
        }
+       device_remove_file(&gadget->dev, &dev_attr_suspended);
        kfree(cdev);
        set_gadget_data(gadget, NULL);
-       device_remove_file(&gadget->dev, &dev_attr_suspended);
        composite = NULL;
 }
 
@@ -1107,14 +1107,6 @@ static int composite_bind(struct usb_gadget *gadget)
         */
        usb_ep_autoconfig_reset(cdev->gadget);
 
-       /* standardized runtime overrides for device ID data */
-       if (idVendor)
-               cdev->desc.idVendor = cpu_to_le16(idVendor);
-       if (idProduct)
-               cdev->desc.idProduct = cpu_to_le16(idProduct);
-       if (bcdDevice)
-               cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
-
        /* composite gadget needs to assign strings for whole device (like
         * serial number), register function drivers, potentially update
         * power state and consumption, etc
@@ -1126,6 +1118,14 @@ static int composite_bind(struct usb_gadget *gadget)
        cdev->desc = *composite->dev;
        cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
+       /* standardized runtime overrides for device ID data */
+       if (idVendor)
+               cdev->desc.idVendor = cpu_to_le16(idVendor);
+       if (idProduct)
+               cdev->desc.idProduct = cpu_to_le16(idProduct);
+       if (bcdDevice)
+               cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);
+
        /* stirng overrides */
        if (iManufacturer || !cdev->desc.iManufacturer) {
                if (!iManufacturer && !composite->iManufacturer &&
index 0fae58ef8afe7c43b145074fd8cbb1fe7b30e248..1d0f45f0e7a62fd191d4c856d0de87715456bfbf 100644 (file)
@@ -1680,6 +1680,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                                xhci->port_array[i] = (u8) -1;
                        }
                        /* FIXME: Should we disable the port? */
+                       continue;
                }
                xhci->port_array[i] = major_revision;
                if (major_revision == 0x03)
@@ -1758,16 +1759,20 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
                        return -ENOMEM;
 
                port_index = 0;
-               for (i = 0; i < num_ports; i++)
-                       if (xhci->port_array[i] != 0x03) {
-                               xhci->usb2_ports[port_index] =
-                                       &xhci->op_regs->port_status_base +
-                                       NUM_PORT_REGS*i;
-                               xhci_dbg(xhci, "USB 2.0 port at index %u, "
-                                               "addr = %p\n", i,
-                                               xhci->usb2_ports[port_index]);
-                               port_index++;
-                       }
+               for (i = 0; i < num_ports; i++) {
+                       if (xhci->port_array[i] == 0x03 ||
+                                       xhci->port_array[i] == 0 ||
+                                       xhci->port_array[i] == -1)
+                               continue;
+
+                       xhci->usb2_ports[port_index] =
+                               &xhci->op_regs->port_status_base +
+                               NUM_PORT_REGS*i;
+                       xhci_dbg(xhci, "USB 2.0 port at index %u, "
+                                       "addr = %p\n", i,
+                                       xhci->usb2_ports[port_index]);
+                       port_index++;
+               }
        }
        if (xhci->num_usb3_ports) {
                xhci->usb3_ports = kmalloc(sizeof(*xhci->usb3_ports)*
index 796e2f68f7494fad857349e9ffc82ac4f9303984..4ff21587ab03214373364681a664df5d56a66a16 100644 (file)
@@ -3,7 +3,7 @@
 /*
  *     uss720.c  --  USS720 USB Parport Cable.
  *
- *     Copyright (C) 1999, 2005
+ *     Copyright (C) 1999, 2005, 2010
  *         Thomas Sailer (t.sailer@alumni.ethz.ch)
  *
  *     This program is free software; you can redistribute it and/or modify
@@ -776,6 +776,8 @@ static const struct usb_device_id uss720_table[] = {
        { USB_DEVICE(0x0557, 0x2001) },
        { USB_DEVICE(0x0729, 0x1284) },
        { USB_DEVICE(0x1293, 0x0002) },
+       { USB_DEVICE(0x1293, 0x0002) },
+       { USB_DEVICE(0x050d, 0x0002) },
        { }                                             /* Terminating entry */
 };
 
index 6a50965e23f29498b2055f4ecbf1912eb3628759..2dec500135282af0c668d58974c7d190519cf1b7 100644 (file)
@@ -796,6 +796,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LOGBOOKML_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_LS_LOGBOOK_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_SCIENCESCOPE_HS_LOGBOOK_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) },
        { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { },                                    /* Optional parameter entry */
index 1286f1e23d8c1505de15be5e1c223128d854055c..bf0867285481bef7f839c5e2c2e7e5fa124f52bd 100644 (file)
 #define MJSG_XM_RADIO_PID      0x937A
 #define MJSG_HD_RADIO_PID      0x937C
 
+/*
+ * D.O.Tec products (http://www.directout.eu)
+ */
+#define FTDI_DOTEC_PID 0x9868
+
 /*
  * Xverve Signalyzer tools (http://www.signalyzer.com/)
  */
index 6ccdd3dd5259b6887fb4b93b5a165feb83b54f51..fcc1e32ce2566332a3bc6ad41b35fdaf5a23e8ff 100644 (file)
@@ -481,6 +481,13 @@ UNUSUAL_DEV(  0x04e8, 0x507c, 0x0220, 0x0220,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_MAX_SECTORS_64),
 
+/* Reported by Vitaly Kuznetsov <vitty@altlinux.ru> */
+UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999,
+               "Samsung",
+               "YP-CP3",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG),
+
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
  * Device uses standards-violating 32-byte Bulk Command Block Wrappers and
  * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
index a4f4546f0be08555f8a2d793b6b94beaae91186f..397d15eb1ea8aee3d4fe870ae87f8b14f161654f 100644 (file)
@@ -242,6 +242,7 @@ static int cr_backlight_remove(struct platform_device *pdev)
        backlight_device_unregister(crp->cr_backlight_device);
        lcd_device_unregister(crp->cr_lcd_device);
        pci_dev_put(lpc_dev);
+       kfree(crp);
 
        return 0;
 }
index 0e6aa3d96a4246f7c05b0274a2295a3275d6d2ac..4ac1201ad6c2fb3229a60e1377f29b4eef78a2eb 100644 (file)
@@ -1458,7 +1458,7 @@ static bool apertures_overlap(struct aperture *gen, struct aperture *hw)
        if (gen->base == hw->base)
                return true;
        /* is the generic aperture base inside the hw base->hw base+size */
-       if (gen->base > hw->base && gen->base <= hw->base + hw->size)
+       if (gen->base > hw->base && gen->base < hw->base + hw->size)
                return true;
        return false;
 }
index 5c363d026f64c2856b44e748ecb149d9242be6b6..1ab2c25886757616c4faa324620ed7536fac9350 100644 (file)
 #define LCDC_SIZE      0x04
 #define SIZE_XMAX(x)   ((((x) >> 4) & 0x3f) << 20)
 
-#ifdef CONFIG_ARCH_MX1
-#define SIZE_YMAX(y)   ((y) & 0x1ff)
-#else
-#define SIZE_YMAX(y)   ((y) & 0x3ff)
-#endif
+#define YMAX_MASK       (cpu_is_mx1() ? 0x1ff : 0x3ff)
+#define SIZE_YMAX(y)   ((y) & YMAX_MASK)
 
 #define LCDC_VPW       0x08
 #define VPW_VPW(x)     ((x) & 0x3ff)
@@ -623,7 +620,7 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
        if (var->right_margin > 255)
                printk(KERN_ERR "%s: invalid right_margin %d\n",
                        info->fix.id, var->right_margin);
-       if (var->yres < 1 || var->yres > 511)
+       if (var->yres < 1 || var->yres > YMAX_MASK)
                printk(KERN_ERR "%s: invalid yres %d\n",
                        info->fix.id, var->yres);
        if (var->vsync_len > 100)
index 455c6055325dcae647858eb6cede512388f033dc..083c8fe53e24147962a1f821657cf1bfcff8608c 100644 (file)
@@ -1,7 +1,7 @@
 config FB_OMAP
        tristate "OMAP frame buffer support (EXPERIMENTAL)"
-       depends on FB && ARCH_OMAP && (OMAP2_DSS = "n")
-
+       depends on FB && (OMAP2_DSS = "n")
+       depends on ARCH_OMAP1 || ARCH_OMAP2 || ARCH_OMAP3
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
index 2fd7e5271be91ea1c9cd5b202ef40f985266dd46..9441e2eb3dee1a1d66259a406d0653da323570e6 100644 (file)
@@ -551,7 +551,7 @@ void __init omap_vram_reserve_sdram_memblock(void)
        if (!size)
                return;
 
-       size = PAGE_ALIGN(size);
+       size = ALIGN(size, SZ_2M);
 
        if (paddr) {
                if (paddr & ~PAGE_MASK) {
@@ -576,7 +576,7 @@ void __init omap_vram_reserve_sdram_memblock(void)
                        return;
                }
        } else {
-               paddr = memblock_alloc(size, PAGE_SIZE);
+               paddr = memblock_alloc(size, SZ_2M);
        }
 
        memblock_free(paddr, size);
index d7df10315d8d6f51aba676328985a52128e81876..fcda0e97011384bd7ee55eaeeed5377f328cf016 100644 (file)
@@ -787,6 +787,9 @@ static int sh_hdmi_read_edid(struct sh_hdmi *hdmi)
                found_rate_error = rate_error;
        }
 
+       hdmi->var.width = hdmi->monspec.max_x * 10;
+       hdmi->var.height = hdmi->monspec.max_y * 10;
+
        /*
         * TODO 1: if no ->info is present, postpone running the config until
         * after ->info first gets registered.
@@ -960,8 +963,12 @@ static bool sh_hdmi_must_reconfigure(struct sh_hdmi *hdmi)
        dev_dbg(info->dev, "Old %ux%u, new %ux%u\n",
                mode1.xres, mode1.yres, mode2.xres, mode2.yres);
 
-       if (fb_mode_is_equal(&mode1, &mode2))
+       if (fb_mode_is_equal(&mode1, &mode2)) {
+               /* It can be a different monitor with an equal video-mode */
+               old_var->width = new_var->width;
+               old_var->height = new_var->height;
                return false;
+       }
 
        dev_dbg(info->dev, "Switching %u -> %u lines\n",
                mode1.yres, mode2.yres);
@@ -1057,8 +1064,11 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
                         * on, if we run a resume here, the logo disappears
                         */
                        if (lock_fb_info(hdmi->info)) {
-                               sh_hdmi_display_on(hdmi, hdmi->info);
-                               unlock_fb_info(hdmi->info);
+                               struct fb_info *info = hdmi->info;
+                               info->var.width = hdmi->var.width;
+                               info->var.height = hdmi->var.height;
+                               sh_hdmi_display_on(hdmi, info);
+                               unlock_fb_info(info);
                        }
                } else {
                        /* New monitor or have to wake up */
index b02d97a879d67256992a3941536fcd7e88626f63..c05326b61235e724e18ea288d88aa66138751899 100644 (file)
@@ -54,8 +54,8 @@ static int lcdc_shared_regs[] = {
 };
 #define NR_SHARED_REGS ARRAY_SIZE(lcdc_shared_regs)
 
-#define DEFAULT_XRES 1280
-#define DEFAULT_YRES 1024
+#define MAX_XRES 1920
+#define MAX_YRES 1080
 
 static unsigned long lcdc_offs_mainlcd[NR_CH_REGS] = {
        [LDDCKPAT1R] = 0x400,
@@ -914,22 +914,12 @@ static int sh_mobile_check_var(struct fb_var_screeninfo *var, struct fb_info *in
 {
        struct sh_mobile_lcdc_chan *ch = info->par;
 
-       if (var->xres < 160 || var->xres > 1920 ||
-           var->yres < 120 || var->yres > 1080 ||
-           var->left_margin < 32 || var->left_margin > 320 ||
-           var->right_margin < 12 || var->right_margin > 240 ||
-           var->upper_margin < 12 || var->upper_margin > 120 ||
-           var->lower_margin < 1 || var->lower_margin > 64 ||
-           var->hsync_len < 32 || var->hsync_len > 240 ||
-           var->vsync_len < 2 || var->vsync_len > 64 ||
-           var->pixclock < 6000 || var->pixclock > 40000 ||
+       if (var->xres > MAX_XRES || var->yres > MAX_YRES ||
            var->xres * var->yres * (ch->cfg.bpp / 8) * 2 > info->fix.smem_len) {
-               dev_warn(info->dev, "Invalid info: %u %u %u %u %u %u %u %u %u!\n",
-                        var->xres, var->yres,
-                        var->left_margin, var->right_margin,
-                        var->upper_margin, var->lower_margin,
-                        var->hsync_len, var->vsync_len,
-                        var->pixclock);
+               dev_warn(info->dev, "Invalid info: %u-%u-%u-%u x %u-%u-%u-%u @ %ukHz!\n",
+                        var->left_margin, var->xres, var->right_margin, var->hsync_len,
+                        var->upper_margin, var->yres, var->lower_margin, var->vsync_len,
+                        PICOS2KHZ(var->pixclock));
                return -EINVAL;
        }
        return 0;
@@ -1226,7 +1216,7 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
                }
 
                if (!mode)
-                       max_size = DEFAULT_XRES * DEFAULT_YRES;
+                       max_size = MAX_XRES * MAX_YRES;
                else if (max_cfg)
                        dev_dbg(&pdev->dev, "Found largest videomode %ux%u\n",
                                max_cfg->xres, max_cfg->yres);
@@ -1238,12 +1228,14 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev)
                        mode = &default_720p;
                        num_cfg = 1;
                } else {
-                       num_cfg = ch->cfg.num_cfg;
+                       num_cfg = cfg->num_cfg;
                }
 
                fb_videomode_to_modelist(mode, num_cfg, &info->modelist);
 
                fb_videomode_to_var(var, mode);
+               var->width = cfg->lcd_size_cfg.width;
+               var->height = cfg->lcd_size_cfg.height;
                /* Default Y virtual resolution is 2x panel size */
                var->yres_virtual = var->yres * 2;
                var->activate = FB_ACTIVATE_NOW;
index 428f8a1583e8598ae69414f8171e21a3bbbf2ba8..3939e53f5f981d327ff344d522ab59f4df43238b 100644 (file)
@@ -231,7 +231,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
        struct resource *r;
        struct rdc321x_wdt_pdata *pdata;
 
-       pdata = pdev->dev.platform_data;
+       pdata = platform_get_drvdata(pdev);
        if (!pdata) {
                dev_err(&pdev->dev, "no platform data supplied\n");
                return -ENODEV;
index 6f0444473594a05df9b08b532c0d9e40f62bdca7..659f532d26a01f6b3b1da403a3834ba116d20bdd 100644 (file)
@@ -166,7 +166,7 @@ static struct dentry *btrfs_fh_to_dentry(struct super_block *sb, struct fid *fh,
 static struct dentry *btrfs_get_parent(struct dentry *child)
 {
        struct inode *dir = child->d_inode;
-       static struct dentry *dentry;
+       struct dentry *dentry;
        struct btrfs_root *root = BTRFS_I(dir)->root;
        struct btrfs_path *path;
        struct extent_buffer *leaf;
index 158c700fdca5e4f62763377a8374217d6371b68b..d902948a90d88622e9af8bbfc505a779fe735d99 100644 (file)
@@ -40,7 +40,8 @@ int ceph_init_dentry(struct dentry *dentry)
        if (dentry->d_fsdata)
                return 0;
 
-       if (ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
+       if (dentry->d_parent == NULL ||   /* nfs fh_to_dentry */
+           ceph_snap(dentry->d_parent->d_inode) == CEPH_NOSNAP)
                dentry->d_op = &ceph_dentry_ops;
        else if (ceph_snap(dentry->d_parent->d_inode) == CEPH_SNAPDIR)
                dentry->d_op = &ceph_snapdir_dentry_ops;
index 8d79b8912e31e4cb8fcb4961ec1f81d63c3d5070..7d0e4a82d898a83f2695eead6ffc767689ffe140 100644 (file)
@@ -282,7 +282,8 @@ int ceph_release(struct inode *inode, struct file *file)
 static int striped_read(struct inode *inode,
                        u64 off, u64 len,
                        struct page **pages, int num_pages,
-                       int *checkeof, bool align_to_pages)
+                       int *checkeof, bool align_to_pages,
+                       unsigned long buf_align)
 {
        struct ceph_fs_client *fsc = ceph_inode_to_client(inode);
        struct ceph_inode_info *ci = ceph_inode(inode);
@@ -307,7 +308,7 @@ static int striped_read(struct inode *inode,
 
 more:
        if (align_to_pages)
-               page_align = (pos - io_align) & ~PAGE_MASK;
+               page_align = (pos - io_align + buf_align) & ~PAGE_MASK;
        else
                page_align = pos & ~PAGE_MASK;
        this_len = left;
@@ -376,16 +377,18 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
        struct inode *inode = file->f_dentry->d_inode;
        struct page **pages;
        u64 off = *poff;
-       int num_pages = calc_pages_for(off, len);
-       int ret;
+       int num_pages, ret;
 
        dout("sync_read on file %p %llu~%u %s\n", file, off, len,
             (file->f_flags & O_DIRECT) ? "O_DIRECT" : "");
 
-       if (file->f_flags & O_DIRECT)
-               pages = ceph_get_direct_page_vector(data, num_pages);
-       else
+       if (file->f_flags & O_DIRECT) {
+               num_pages = calc_pages_for((unsigned long)data, len);
+               pages = ceph_get_direct_page_vector(data, num_pages, true);
+       } else {
+               num_pages = calc_pages_for(off, len);
                pages = ceph_alloc_page_vector(num_pages, GFP_NOFS);
+       }
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
@@ -400,7 +403,8 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
                goto done;
 
        ret = striped_read(inode, off, len, pages, num_pages, checkeof,
-                          file->f_flags & O_DIRECT);
+                          file->f_flags & O_DIRECT,
+                          (unsigned long)data & ~PAGE_MASK);
 
        if (ret >= 0 && (file->f_flags & O_DIRECT) == 0)
                ret = ceph_copy_page_vector_to_user(pages, data, off, ret);
@@ -409,7 +413,7 @@ static ssize_t ceph_sync_read(struct file *file, char __user *data,
 
 done:
        if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages);
+               ceph_put_page_vector(pages, num_pages, true);
        else
                ceph_release_page_vector(pages, num_pages);
        dout("sync_read result %d\n", ret);
@@ -456,6 +460,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
        int do_sync = 0;
        int check_caps = 0;
        int page_align, io_align;
+       unsigned long buf_align;
        int ret;
        struct timespec mtime = CURRENT_TIME;
 
@@ -471,6 +476,7 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
                pos = *offset;
 
        io_align = pos & ~PAGE_MASK;
+       buf_align = (unsigned long)data & ~PAGE_MASK;
 
        ret = filemap_write_and_wait_range(inode->i_mapping, pos, pos + left);
        if (ret < 0)
@@ -496,12 +502,15 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data,
         */
 more:
        len = left;
-       if (file->f_flags & O_DIRECT)
+       if (file->f_flags & O_DIRECT) {
                /* write from beginning of first page, regardless of
                   io alignment */
-               page_align = (pos - io_align) & ~PAGE_MASK;
-       else
+               page_align = (pos - io_align + buf_align) & ~PAGE_MASK;
+               num_pages = calc_pages_for((unsigned long)data, len);
+       } else {
                page_align = pos & ~PAGE_MASK;
+               num_pages = calc_pages_for(pos, len);
+       }
        req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout,
                                    ceph_vino(inode), pos, &len,
                                    CEPH_OSD_OP_WRITE, flags,
@@ -512,10 +521,8 @@ more:
        if (!req)
                return -ENOMEM;
 
-       num_pages = calc_pages_for(pos, len);
-
        if (file->f_flags & O_DIRECT) {
-               pages = ceph_get_direct_page_vector(data, num_pages);
+               pages = ceph_get_direct_page_vector(data, num_pages, false);
                if (IS_ERR(pages)) {
                        ret = PTR_ERR(pages);
                        goto out;
@@ -565,7 +572,7 @@ more:
        }
 
        if (file->f_flags & O_DIRECT)
-               ceph_put_page_vector(pages, num_pages);
+               ceph_put_page_vector(pages, num_pages, false);
        else if (file->f_flags & O_SYNC)
                ceph_release_page_vector(pages, num_pages);
 
index dc963929de652cb997550e38338855823832e53c..981c8477adab6dcde6708d2b8bfde8bf83c8d53b 100644 (file)
@@ -232,6 +232,8 @@ static int setup_new_group_blocks(struct super_block *sb,
                               GFP_NOFS);
        if (err)
                goto exit_bh;
+       for (i = 0, bit = gdblocks + 1; i < reserved_gdb; i++, bit++)
+               ext4_set_bit(bit, bh->b_data);
 
        ext4_debug("mark block bitmap %#04llx (+%llu)\n", input->block_bitmap,
                   input->block_bitmap - start);
@@ -247,6 +249,9 @@ static int setup_new_group_blocks(struct super_block *sb,
        err = sb_issue_zeroout(sb, block, sbi->s_itb_per_group, GFP_NOFS);
        if (err)
                goto exit_bh;
+       for (i = 0, bit = input->inode_table - start;
+            i < sbi->s_itb_per_group; i++, bit++)
+               ext4_set_bit(bit, bh->b_data);
 
        if ((err = extend_or_restart_transaction(handle, 2, bh)))
                goto exit_bh;
index f46ee8b0e135eb62d00e45dc30bbee31c61c213a..9da29706f91cd74772169e6391333ae877a1fa05 100644 (file)
@@ -828,7 +828,7 @@ void do_logfs_journal_wl_pass(struct super_block *sb)
                super->s_journal_seg[i] = segno;
                super->s_journal_ec[i] = ec;
                logfs_set_segment_reserved(sb, segno);
-               err = btree_insert32(head, segno, (void *)1, GFP_KERNEL);
+               err = btree_insert32(head, segno, (void *)1, GFP_NOFS);
                BUG_ON(err); /* mempool should prevent this */
                err = logfs_erase_segment(sb, segno, 1);
                BUG_ON(err); /* FIXME: remount-ro would be nicer */
index 6127baf0e1884760e757d656a772cf13d3953be2..ee99a9f5dfd3ac251b6b824a1032ce45b68b6ed7 100644 (file)
@@ -1994,6 +1994,9 @@ static int do_write_inode(struct inode *inode)
 
        /* FIXME: transaction is part of logfs_block now.  Is that enough? */
        err = logfs_write_buf(master_inode, page, 0);
+       if (err)
+               move_page_to_inode(inode, page);
+
        logfs_put_write_page(page);
        return err;
 }
index 5362af9b73729905817a76b5c24a5b33c48d5ce7..4ff7ca530533b121763dbe3b415ad79b162a85fb 100644 (file)
@@ -1748,6 +1748,9 @@ struct file *do_filp_open(int dfd, const char *pathname,
        if (!(open_flag & O_CREAT))
                mode = 0;
 
+       /* Must never be set by userspace */
+       open_flag &= ~FMODE_NONOTIFY;
+
        /*
         * O_SYNC is implemented as __O_SYNC|O_DSYNC.  As many places only
         * check for O_DSYNC if the need any syncing at all we enforce it's
index 33ad25ddd5c442a7875e8eca9b078b363e10d9ce..caf9a6a3fb54f0e0dd4cd63ccf103fd6aef20a70 100644 (file)
@@ -176,7 +176,6 @@ int nilfs_gccache_wait_and_mark_dirty(struct buffer_head *bh)
 int nilfs_init_gcinode(struct inode *inode)
 {
        struct nilfs_inode_info *ii = NILFS_I(inode);
-       struct the_nilfs *nilfs = NILFS_SB(inode->i_sb)->s_nilfs;
 
        inode->i_mode = S_IFREG;
        mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
@@ -186,14 +185,6 @@ int nilfs_init_gcinode(struct inode *inode)
        ii->i_flags = 0;
        nilfs_bmap_init_gc(ii->i_bmap);
 
-       /*
-        * Add the inode to GC inode list. Garbage Collection
-        * is serialized and no two processes manipulate the
-        * list simultaneously.
-        */
-       igrab(inode);
-       list_add(&NILFS_I(inode)->i_dirty, &nilfs->ns_gc_inodes);
-
        return 0;
 }
 
index e00d9457c256179279b141868d6ed86494dec24e..b185e937a335471ec224314909a959684f56d174 100644 (file)
@@ -337,6 +337,7 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                                   struct nilfs_argv *argv, void *buf)
 {
        size_t nmembs = argv->v_nmembs;
+       struct the_nilfs *nilfs = NILFS_SB(sb)->s_nilfs;
        struct inode *inode;
        struct nilfs_vdesc *vdesc;
        struct buffer_head *bh, *n;
@@ -353,6 +354,17 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb,
                        ret = PTR_ERR(inode);
                        goto failed;
                }
+               if (list_empty(&NILFS_I(inode)->i_dirty)) {
+                       /*
+                        * Add the inode to GC inode list. Garbage Collection
+                        * is serialized and no two processes manipulate the
+                        * list simultaneously.
+                        */
+                       igrab(inode);
+                       list_add(&NILFS_I(inode)->i_dirty,
+                                &nilfs->ns_gc_inodes);
+               }
+
                do {
                        ret = nilfs_ioctl_move_inode_block(inode, vdesc,
                                                           &buffers);
index b04f88eed09e98b6134f275cb7ba530a06e7f998..f35794b97e8e5cb5cc396af28206d69ca1202935 100644 (file)
@@ -92,7 +92,11 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group,
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       wait_event(group->fanotify_data.access_waitq, event->response);
+       wait_event(group->fanotify_data.access_waitq, event->response ||
+                               atomic_read(&group->fanotify_data.bypass_perm));
+
+       if (!event->response) /* bypass_perm set */
+               return 0;
 
        /* userspace responded, convert to something usable */
        spin_lock(&event->lock);
index 063224812b7e607879bffeedd5b90f9c4967346f..8b61220cffc597873bc0292bbf2fcd86300f3d5c 100644 (file)
@@ -106,20 +106,29 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
        return client_fd;
 }
 
-static ssize_t fill_event_metadata(struct fsnotify_group *group,
+static int fill_event_metadata(struct fsnotify_group *group,
                                   struct fanotify_event_metadata *metadata,
                                   struct fsnotify_event *event)
 {
+       int ret = 0;
+
        pr_debug("%s: group=%p metadata=%p event=%p\n", __func__,
                 group, metadata, event);
 
        metadata->event_len = FAN_EVENT_METADATA_LEN;
+       metadata->metadata_len = FAN_EVENT_METADATA_LEN;
        metadata->vers = FANOTIFY_METADATA_VERSION;
        metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS;
        metadata->pid = pid_vnr(event->tgid);
-       metadata->fd = create_fd(group, event);
+       if (unlikely(event->mask & FAN_Q_OVERFLOW))
+               metadata->fd = FAN_NOFD;
+       else {
+               metadata->fd = create_fd(group, event);
+               if (metadata->fd < 0)
+                       ret = metadata->fd;
+       }
 
-       return metadata->fd;
+       return ret;
 }
 
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
@@ -200,7 +209,7 @@ static int prepare_for_access_response(struct fsnotify_group *group,
 
        mutex_lock(&group->fanotify_data.access_mutex);
 
-       if (group->fanotify_data.bypass_perm) {
+       if (atomic_read(&group->fanotify_data.bypass_perm)) {
                mutex_unlock(&group->fanotify_data.access_mutex);
                kmem_cache_free(fanotify_response_event_cache, re);
                event->response = FAN_ALLOW;
@@ -257,24 +266,34 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-       fd = fill_event_metadata(group, &fanotify_event_metadata, event);
-       if (fd < 0)
-               return fd;
+       ret = fill_event_metadata(group, &fanotify_event_metadata, event);
+       if (ret < 0)
+               goto out;
 
+       fd = fanotify_event_metadata.fd;
        ret = prepare_for_access_response(group, event, fd);
        if (ret)
                goto out_close_fd;
 
        ret = -EFAULT;
-       if (copy_to_user(buf, &fanotify_event_metadata, FAN_EVENT_METADATA_LEN))
+       if (copy_to_user(buf, &fanotify_event_metadata,
+                        fanotify_event_metadata.event_len))
                goto out_kill_access_response;
 
-       return FAN_EVENT_METADATA_LEN;
+       return fanotify_event_metadata.event_len;
 
 out_kill_access_response:
        remove_access_response(group, event, fd);
 out_close_fd:
-       sys_close(fd);
+       if (fd != FAN_NOFD)
+               sys_close(fd);
+out:
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+       if (event->mask & FAN_ALL_PERM_EVENTS) {
+               event->response = FAN_DENY;
+               wake_up(&group->fanotify_data.access_waitq);
+       }
+#endif
        return ret;
 }
 
@@ -382,7 +401,7 @@ static int fanotify_release(struct inode *ignored, struct file *file)
 
        mutex_lock(&group->fanotify_data.access_mutex);
 
-       group->fanotify_data.bypass_perm = true;
+       atomic_inc(&group->fanotify_data.bypass_perm);
 
        list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) {
                pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group,
@@ -586,11 +605,10 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
+       int ret = 0;
 
        fsn_mark = fsnotify_find_vfsmount_mark(group, mnt);
        if (!fsn_mark) {
-               int ret;
-
                if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
                        return -ENOSPC;
 
@@ -600,17 +618,16 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
 
                fsnotify_init_mark(fsn_mark, fanotify_free_mark);
                ret = fsnotify_add_mark(fsn_mark, group, NULL, mnt, 0);
-               if (ret) {
-                       fanotify_free_mark(fsn_mark);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
        }
        added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
-       fsnotify_put_mark(fsn_mark);
+
        if (added & ~mnt->mnt_fsnotify_mask)
                fsnotify_recalc_vfsmount_mask(mnt);
-
-       return 0;
+err:
+       fsnotify_put_mark(fsn_mark);
+       return ret;
 }
 
 static int fanotify_add_inode_mark(struct fsnotify_group *group,
@@ -619,6 +636,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 {
        struct fsnotify_mark *fsn_mark;
        __u32 added;
+       int ret = 0;
 
        pr_debug("%s: group=%p inode=%p\n", __func__, group, inode);
 
@@ -634,8 +652,6 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 
        fsn_mark = fsnotify_find_inode_mark(group, inode);
        if (!fsn_mark) {
-               int ret;
-
                if (atomic_read(&group->num_marks) > group->fanotify_data.max_marks)
                        return -ENOSPC;
 
@@ -645,16 +661,16 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
 
                fsnotify_init_mark(fsn_mark, fanotify_free_mark);
                ret = fsnotify_add_mark(fsn_mark, group, inode, NULL, 0);
-               if (ret) {
-                       fanotify_free_mark(fsn_mark);
-                       return ret;
-               }
+               if (ret)
+                       goto err;
        }
        added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
-       fsnotify_put_mark(fsn_mark);
+
        if (added & ~inode->i_fsnotify_mask)
                fsnotify_recalc_inode_mask(inode);
-       return 0;
+err:
+       fsnotify_put_mark(fsn_mark);
+       return ret;
 }
 
 /* fanotify syscalls */
@@ -687,8 +703,10 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 
        /* fsnotify_alloc_group takes a ref.  Dropped in fanotify_release */
        group = fsnotify_alloc_group(&fanotify_fsnotify_ops);
-       if (IS_ERR(group))
+       if (IS_ERR(group)) {
+               free_uid(user);
                return PTR_ERR(group);
+       }
 
        group->fanotify_data.user = user;
        atomic_inc(&user->fanotify_listeners);
@@ -698,6 +716,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        mutex_init(&group->fanotify_data.access_mutex);
        init_waitqueue_head(&group->fanotify_data.access_waitq);
        INIT_LIST_HEAD(&group->fanotify_data.access_list);
+       atomic_set(&group->fanotify_data.bypass_perm, 0);
 #endif
        switch (flags & FAN_ALL_CLASS_BITS) {
        case FAN_CLASS_NOTIF:
@@ -764,8 +783,10 @@ SYSCALL_DEFINE(fanotify_mark)(int fanotify_fd, unsigned int flags,
        if (flags & ~FAN_ALL_MARK_FLAGS)
                return -EINVAL;
        switch (flags & (FAN_MARK_ADD | FAN_MARK_REMOVE | FAN_MARK_FLUSH)) {
-       case FAN_MARK_ADD:
+       case FAN_MARK_ADD:              /* fallthrough */
        case FAN_MARK_REMOVE:
+               if (!mask)
+                       return -EINVAL;
        case FAN_MARK_FLUSH:
                break;
        default:
index 444c305a468c531b7e9e8dda803a2d650a257c58..4cd5d5d78f9fa2b85f38bd9422efc3d387780295 100644 (file)
@@ -752,6 +752,7 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
        if (ret >= 0)
                return ret;
 
+       fsnotify_put_group(group);
        atomic_dec(&user->inotify_devs);
 out_free_uid:
        free_uid(user);
index f1e962cb3b73084699a182933b7760926c36880e..0d7c5540ad669a55d4def39f21bbe7b42bfb83cc 100644 (file)
@@ -573,11 +573,14 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
        /* this io's submitter should not have unlocked this before we could */
        BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
 
+       if (ocfs2_iocb_is_sem_locked(iocb)) {
+               up_read(&inode->i_alloc_sem);
+               ocfs2_iocb_clear_sem_locked(iocb);
+       }
+
        ocfs2_iocb_clear_rw_locked(iocb);
 
        level = ocfs2_iocb_rw_locked_level(iocb);
-       if (!level)
-               up_read(&inode->i_alloc_sem);
        ocfs2_rw_unlock(inode, level);
 
        if (is_async)
index 76bfdfda691a03b1790ac9670a8bb79d042e7584..eceb456037c11c7a2e68cc2d510908ef781cfdbf 100644 (file)
@@ -68,8 +68,27 @@ static inline void ocfs2_iocb_set_rw_locked(struct kiocb *iocb, int level)
        else
                clear_bit(1, (unsigned long *)&iocb->private);
 }
+
+/*
+ * Using a named enum representing lock types in terms of #N bit stored in
+ * iocb->private, which is going to be used for communication bewteen
+ * ocfs2_dio_end_io() and ocfs2_file_aio_write/read().
+ */
+enum ocfs2_iocb_lock_bits {
+       OCFS2_IOCB_RW_LOCK = 0,
+       OCFS2_IOCB_RW_LOCK_LEVEL,
+       OCFS2_IOCB_SEM,
+       OCFS2_IOCB_NUM_LOCKS
+};
+
 #define ocfs2_iocb_clear_rw_locked(iocb) \
-       clear_bit(0, (unsigned long *)&iocb->private)
+       clear_bit(OCFS2_IOCB_RW_LOCK, (unsigned long *)&iocb->private)
 #define ocfs2_iocb_rw_locked_level(iocb) \
-       test_bit(1, (unsigned long *)&iocb->private)
+       test_bit(OCFS2_IOCB_RW_LOCK_LEVEL, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_set_sem_locked(iocb) \
+       set_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_clear_sem_locked(iocb) \
+       clear_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_is_sem_locked(iocb) \
+       test_bit(OCFS2_IOCB_SEM, (unsigned long *)&iocb->private)
 #endif /* OCFS2_FILE_H */
index c7fba396392d8c0a866c5194204eb1abb49d827d..6c61771469af24ef9e2610e93e65092768b59691 100644 (file)
@@ -113,10 +113,11 @@ static struct mlog_attribute mlog_attrs[MLOG_MAX_BITS] = {
        define_mask(QUOTA),
        define_mask(REFCOUNT),
        define_mask(BASTS),
+       define_mask(RESERVATIONS),
+       define_mask(CLUSTER),
        define_mask(ERROR),
        define_mask(NOTICE),
        define_mask(KTHREAD),
-       define_mask(RESERVATIONS),
 };
 
 static struct attribute *mlog_attr_ptrs[MLOG_MAX_BITS] = {NULL, };
index ea2ed9f56c94ad0654a5f79259e50a1f046bed97..34d6544357d9718699af25e25aecc48a1f26c9c0 100644 (file)
@@ -81,7 +81,7 @@
 #include <linux/sched.h>
 
 /* bits that are frequently given and infrequently matched in the low word */
-/* NOTE: If you add a flag, you need to also update mlog.c! */
+/* NOTE: If you add a flag, you need to also update masklog.c! */
 #define ML_ENTRY       0x0000000000000001ULL /* func call entry */
 #define ML_EXIT                0x0000000000000002ULL /* func call exit */
 #define ML_TCP         0x0000000000000004ULL /* net cluster/tcp.c */
 #define ML_XATTR       0x0000000020000000ULL /* ocfs2 extended attributes */
 #define ML_QUOTA       0x0000000040000000ULL /* ocfs2 quota operations */
 #define ML_REFCOUNT    0x0000000080000000ULL /* refcount tree operations */
-#define ML_BASTS       0x0000001000000000ULL /* dlmglue asts and basts */
+#define ML_BASTS       0x0000000100000000ULL /* dlmglue asts and basts */
+#define ML_RESERVATIONS        0x0000000200000000ULL /* ocfs2 alloc reservations */
+#define ML_CLUSTER     0x0000000400000000ULL /* cluster stack */
+
 /* bits that are infrequently given and frequently matched in the high word */
-#define ML_ERROR       0x0000000100000000ULL /* sent to KERN_ERR */
-#define ML_NOTICE      0x0000000200000000ULL /* setn to KERN_NOTICE */
-#define ML_KTHREAD     0x0000000400000000ULL /* kernel thread activity */
-#define ML_RESERVATIONS        0x0000000800000000ULL /* ocfs2 alloc reservations */
-#define ML_CLUSTER     0x0000001000000000ULL /* cluster stack */
+#define ML_ERROR       0x1000000000000000ULL /* sent to KERN_ERR */
+#define ML_NOTICE      0x2000000000000000ULL /* setn to KERN_NOTICE */
+#define ML_KTHREAD     0x4000000000000000ULL /* kernel thread activity */
 
 #define MLOG_INITIAL_AND_MASK (ML_ERROR|ML_NOTICE)
 #define MLOG_INITIAL_NOT_MASK (ML_ENTRY|ML_EXIT)
index c49f6de0e7abb6e096ddc56e795957e0194bb8dd..d417b3f9b0c730e5cbb8d475358e6d8891fdc05c 100644 (file)
@@ -2461,8 +2461,10 @@ static int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
 
        di->i_dx_root = cpu_to_le64(dr_blkno);
 
+       spin_lock(&OCFS2_I(dir)->ip_lock);
        OCFS2_I(dir)->ip_dyn_features |= OCFS2_INDEXED_DIR_FL;
        di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
+       spin_unlock(&OCFS2_I(dir)->ip_lock);
 
        ocfs2_journal_dirty(handle, di_bh);
 
@@ -4466,8 +4468,10 @@ static int ocfs2_dx_dir_remove_index(struct inode *dir,
                goto out_commit;
        }
 
+       spin_lock(&OCFS2_I(dir)->ip_lock);
        OCFS2_I(dir)->ip_dyn_features &= ~OCFS2_INDEXED_DIR_FL;
        di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
+       spin_unlock(&OCFS2_I(dir)->ip_lock);
        di->i_dx_root = cpu_to_le64(0ULL);
 
        ocfs2_journal_dirty(handle, di_bh);
index f564b0e5f80d8c89e08eeba4a5e133b24cb67373..59f0f6bdfc62110141ca7ad413dc51abadd4b3c8 100644 (file)
@@ -2346,7 +2346,8 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
  */
 static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
                                      struct dlm_lock_resource *res,
-                                     int *numlocks)
+                                     int *numlocks,
+                                     int *hasrefs)
 {
        int ret;
        int i;
@@ -2356,6 +2357,9 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
 
        assert_spin_locked(&res->spinlock);
 
+       *numlocks = 0;
+       *hasrefs = 0;
+
        ret = -EINVAL;
        if (res->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
                mlog(0, "cannot migrate lockres with unknown owner!\n");
@@ -2386,7 +2390,13 @@ static int dlm_is_lockres_migrateable(struct dlm_ctxt *dlm,
        }
 
        *numlocks = count;
-       mlog(0, "migrateable lockres having %d locks\n", *numlocks);
+
+       count = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
+       if (count < O2NM_MAX_NODES)
+               *hasrefs = 1;
+
+       mlog(0, "%s: res %.*s, Migrateable, locks %d, refs %d\n", dlm->name,
+            res->lockname.len, res->lockname.name, *numlocks, *hasrefs);
 
 leave:
        return ret;
@@ -2408,7 +2418,7 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
        const char *name;
        unsigned int namelen;
        int mle_added = 0;
-       int numlocks;
+       int numlocks, hasrefs;
        int wake = 0;
 
        if (!dlm_grab(dlm))
@@ -2417,13 +2427,13 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
        name = res->lockname.name;
        namelen = res->lockname.len;
 
-       mlog(0, "migrating %.*s to %u\n", namelen, name, target);
+       mlog(0, "%s: Migrating %.*s to %u\n", dlm->name, namelen, name, target);
 
        /*
         * ensure this lockres is a proper candidate for migration
         */
        spin_lock(&res->spinlock);
-       ret = dlm_is_lockres_migrateable(dlm, res, &numlocks);
+       ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs);
        if (ret < 0) {
                spin_unlock(&res->spinlock);
                goto leave;
@@ -2431,10 +2441,8 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
        spin_unlock(&res->spinlock);
 
        /* no work to do */
-       if (numlocks == 0) {
-               mlog(0, "no locks were found on this lockres! done!\n");
+       if (numlocks == 0 && !hasrefs)
                goto leave;
-       }
 
        /*
         * preallocate up front
@@ -2459,14 +2467,14 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
         * find a node to migrate the lockres to
         */
 
-       mlog(0, "picking a migration node\n");
        spin_lock(&dlm->spinlock);
        /* pick a new node */
        if (!test_bit(target, dlm->domain_map) ||
            target >= O2NM_MAX_NODES) {
                target = dlm_pick_migration_target(dlm, res);
        }
-       mlog(0, "node %u chosen for migration\n", target);
+       mlog(0, "%s: res %.*s, Node %u chosen for migration\n", dlm->name,
+            namelen, name, target);
 
        if (target >= O2NM_MAX_NODES ||
            !test_bit(target, dlm->domain_map)) {
@@ -2667,7 +2675,7 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
 {
        int ret;
        int lock_dropped = 0;
-       int numlocks;
+       int numlocks, hasrefs;
 
        spin_lock(&res->spinlock);
        if (res->owner != dlm->node_num) {
@@ -2681,8 +2689,8 @@ int dlm_empty_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
        }
 
        /* No need to migrate a lockres having no locks */
-       ret = dlm_is_lockres_migrateable(dlm, res, &numlocks);
-       if (ret >= 0 && numlocks == 0) {
+       ret = dlm_is_lockres_migrateable(dlm, res, &numlocks, &hasrefs);
+       if (ret >= 0 && numlocks == 0 && !hasrefs) {
                spin_unlock(&res->spinlock);
                goto leave;
        }
@@ -2915,6 +2923,12 @@ static u8 dlm_pick_migration_target(struct dlm_ctxt *dlm,
                }
                queue++;
        }
+
+       nodenum = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
+       if (nodenum < O2NM_MAX_NODES) {
+               spin_unlock(&res->spinlock);
+               return nodenum;
+       }
        spin_unlock(&res->spinlock);
        mlog(0, "have not found a suitable target yet! checking domain map\n");
 
index 77b4c04a2809831e7209d1be3f8e860a0ba7edc8..f6cba566429d314fe82f9f433889d1e22111462a 100644 (file)
@@ -2241,11 +2241,15 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
 
        mutex_lock(&inode->i_mutex);
 
+       ocfs2_iocb_clear_sem_locked(iocb);
+
 relock:
        /* to match setattr's i_mutex -> i_alloc_sem -> rw_lock ordering */
        if (direct_io) {
                down_read(&inode->i_alloc_sem);
                have_alloc_sem = 1;
+               /* communicate with ocfs2_dio_end_io */
+               ocfs2_iocb_set_sem_locked(iocb);
        }
 
        /*
@@ -2382,8 +2386,10 @@ out:
                ocfs2_rw_unlock(inode, rw_level);
 
 out_sems:
-       if (have_alloc_sem)
+       if (have_alloc_sem) {
                up_read(&inode->i_alloc_sem);
+               ocfs2_iocb_clear_sem_locked(iocb);
+       }
 
        mutex_unlock(&inode->i_mutex);
 
@@ -2527,6 +2533,8 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
                goto bail;
        }
 
+       ocfs2_iocb_clear_sem_locked(iocb);
+
        /*
         * buffered reads protect themselves in ->readpage().  O_DIRECT reads
         * need locks to protect pending reads from racing with truncate.
@@ -2534,6 +2542,7 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
        if (filp->f_flags & O_DIRECT) {
                down_read(&inode->i_alloc_sem);
                have_alloc_sem = 1;
+               ocfs2_iocb_set_sem_locked(iocb);
 
                ret = ocfs2_rw_lock(inode, 0);
                if (ret < 0) {
@@ -2575,8 +2584,10 @@ static ssize_t ocfs2_file_aio_read(struct kiocb *iocb,
        }
 
 bail:
-       if (have_alloc_sem)
+       if (have_alloc_sem) {
                up_read(&inode->i_alloc_sem);
+               ocfs2_iocb_clear_sem_locked(iocb);
+       }
        if (rw_level != -1)
                ocfs2_rw_unlock(inode, rw_level);
        mlog_exit(ret);
index c2e4f8222e2f0ac707de217555bee7edd51f76d6..bf2e7764920e92e3d621a94caac7124b3fa15914 100644 (file)
@@ -350,7 +350,7 @@ enum {
 #define OCFS2_LAST_LOCAL_SYSTEM_INODE LOCAL_GROUP_QUOTA_SYSTEM_INODE
        NUM_SYSTEM_INODES
 };
-#define NUM_GLOBAL_SYSTEM_INODES OCFS2_LAST_GLOBAL_SYSTEM_INODE
+#define NUM_GLOBAL_SYSTEM_INODES OCFS2_FIRST_LOCAL_SYSTEM_INODE
 #define NUM_LOCAL_SYSTEM_INODES        \
                (NUM_SYSTEM_INODES - OCFS2_FIRST_LOCAL_SYSTEM_INODE)
 
index 2367fb3f70bc6ba468ab0ccb628b5b88fabac955..74802bc5ded95e09d510bcadfba94167e1390bc2 100644 (file)
@@ -499,7 +499,7 @@ static int __init parse_crash_elf64_headers(void)
        /* Do some basic Verification. */
        if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0 ||
                (ehdr.e_type != ET_CORE) ||
-               !vmcore_elf_check_arch(&ehdr) ||
+               !vmcore_elf64_check_arch(&ehdr) ||
                ehdr.e_ident[EI_CLASS] != ELFCLASS64 ||
                ehdr.e_ident[EI_VERSION] != EV_CURRENT ||
                ehdr.e_version != EV_CURRENT ||
index c6454cca044787f65965369d92837f4649297a93..9e7f259346e1e25dc3fc44a9078604d892a81aa1 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/resource.h>
+#include <linux/regulator/consumer.h>
 
 #define AMBA_NR_IRQS   2
 #define AMBA_CID       0xb105f00d
@@ -28,6 +29,7 @@ struct amba_device {
        struct device           dev;
        struct resource         res;
        struct clk              *pclk;
+       struct regulator        *vcore;
        u64                     dma_mask;
        unsigned int            periphid;
        unsigned int            irq[AMBA_NR_IRQS];
@@ -71,6 +73,12 @@ void amba_release_regions(struct amba_device *);
 #define amba_pclk_disable(d)   \
        do { if (!IS_ERR((d)->pclk)) clk_disable((d)->pclk); } while (0)
 
+#define amba_vcore_enable(d)   \
+       (IS_ERR((d)->vcore) ? 0 : regulator_enable((d)->vcore))
+
+#define amba_vcore_disable(d)  \
+       do { if (!IS_ERR((d)->vcore)) regulator_disable((d)->vcore); } while (0)
+
 /* Some drivers don't use the struct amba_device */
 #define AMBA_CONFIG_BITS(a) (((a) >> 24) & 0xff)
 #define AMBA_REV_BITS(a) (((a) >> 20) & 0x0f)
index 6021588ba0a87ea14ab1cb4620bef7aeea3d3ab9..5479fdc849e9432d9b162c399205c59faf8250c6 100644 (file)
 #define UART01x_LCRH_PEN       0x02
 #define UART01x_LCRH_BRK       0x01
 
+#define ST_UART011_DMAWM_RX_1  (0 << 3)
+#define ST_UART011_DMAWM_RX_2  (1 << 3)
+#define ST_UART011_DMAWM_RX_4  (2 << 3)
+#define ST_UART011_DMAWM_RX_8  (3 << 3)
+#define ST_UART011_DMAWM_RX_16 (4 << 3)
+#define ST_UART011_DMAWM_RX_32 (5 << 3)
+#define ST_UART011_DMAWM_RX_48 (6 << 3)
+#define ST_UART011_DMAWM_TX_1  0
+#define ST_UART011_DMAWM_TX_2  1
+#define ST_UART011_DMAWM_TX_4  2
+#define ST_UART011_DMAWM_TX_8  3
+#define ST_UART011_DMAWM_TX_16 4
+#define ST_UART011_DMAWM_TX_32 5
+#define ST_UART011_DMAWM_TX_48 6
+
 #define UART010_IIR_RTIS       0x08
 #define UART010_IIR_TIS                0x04
 #define UART010_IIR_RIS                0x02
@@ -180,6 +195,13 @@ struct amba_device; /* in uncompress this is included but amba/bus.h is not */
 struct amba_pl010_data {
        void (*set_mctrl)(struct amba_device *dev, void __iomem *base, unsigned int mctrl);
 };
+
+struct dma_chan;
+struct amba_pl011_data {
+       bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+       void *dma_rx_param;
+       void *dma_tx_param;
+};
 #endif
 
 #endif
index aae86fd10c4f5dcea0eaf43cf6c39667a805dae4..36ab42c9bb991566dc5004fad9ca3c0c958bfeb0 100644 (file)
@@ -250,7 +250,7 @@ struct queue_limits {
 
        unsigned char           misaligned;
        unsigned char           discard_misaligned;
-       unsigned char           no_cluster;
+       unsigned char           cluster;
        signed char             discard_zeroes_data;
 };
 
@@ -380,7 +380,6 @@ struct request_queue
 #endif
 };
 
-#define QUEUE_FLAG_CLUSTER     0       /* cluster several segments into 1 */
 #define QUEUE_FLAG_QUEUED      1       /* uses generic tag queueing */
 #define QUEUE_FLAG_STOPPED     2       /* queue is stopped */
 #define        QUEUE_FLAG_SYNCFULL     3       /* read queue has been filled */
@@ -403,7 +402,6 @@ struct request_queue
 #define QUEUE_FLAG_SECDISCARD  19      /* supports SECDISCARD */
 
 #define QUEUE_FLAG_DEFAULT     ((1 << QUEUE_FLAG_IO_STAT) |            \
-                                (1 << QUEUE_FLAG_CLUSTER) |            \
                                 (1 << QUEUE_FLAG_STACKABLE)    |       \
                                 (1 << QUEUE_FLAG_SAME_COMP)    |       \
                                 (1 << QUEUE_FLAG_ADD_RANDOM))
@@ -510,6 +508,11 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q)
 
 #define rq_data_dir(rq)                ((rq)->cmd_flags & 1)
 
+static inline unsigned int blk_queue_cluster(struct request_queue *q)
+{
+       return q->limits.cluster;
+}
+
 /*
  * We regard a request as sync, if either a read or a sync write
  */
@@ -805,6 +808,7 @@ extern struct request_queue *blk_init_allocated_queue(struct request_queue *,
 extern void blk_cleanup_queue(struct request_queue *);
 extern void blk_queue_make_request(struct request_queue *, make_request_fn *);
 extern void blk_queue_bounce_limit(struct request_queue *, u64);
+extern void blk_limits_max_hw_sectors(struct queue_limits *, unsigned int);
 extern void blk_queue_max_hw_sectors(struct request_queue *, unsigned int);
 extern void blk_queue_max_segments(struct request_queue *, unsigned short);
 extern void blk_queue_max_segment_size(struct request_queue *, unsigned int);
index 266ab92912327bb7bfe9bf1d87ff008260cc424f..499dfe982a0e8a21066e815daa400ac8b57ec5b4 100644 (file)
@@ -105,6 +105,8 @@ extern void *__alloc_bootmem_low_node(pg_data_t *pgdat,
 
 #define alloc_bootmem(x) \
        __alloc_bootmem(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
+#define alloc_bootmem_align(x, align) \
+       __alloc_bootmem(x, align, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_nopanic(x) \
        __alloc_bootmem_nopanic(x, SMP_CACHE_BYTES, __pa(MAX_DMA_ADDRESS))
 #define alloc_bootmem_pages(x) \
index 9e76d35670d204d6425b20d17595737fde4453ff..72c72bfccb88181b8b7c480e445849bfc0c8ab28 100644 (file)
@@ -227,8 +227,10 @@ extern int ceph_open_session(struct ceph_client *client);
 extern void ceph_release_page_vector(struct page **pages, int num_pages);
 
 extern struct page **ceph_get_direct_page_vector(const char __user *data,
-                                                int num_pages);
-extern void ceph_put_page_vector(struct page **pages, int num_pages);
+                                                int num_pages,
+                                                bool write_page);
+extern void ceph_put_page_vector(struct page **pages, int num_pages,
+                                bool dirty);
 extern void ceph_release_page_vector(struct page **pages, int num_pages);
 extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
 extern int ceph_copy_user_to_page_vector(struct page **pages,
diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h
new file mode 100644 (file)
index 0000000..457bcb0
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ *  include/linux/clkdev.h
+ *
+ *  Copyright (C) 2008 Russell King.
+ *
+ * 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.
+ *
+ * Helper for the clk API to assist looking up a struct clk.
+ */
+#ifndef __CLKDEV_H
+#define __CLKDEV_H
+
+#include <asm/clkdev.h>
+
+struct clk;
+struct device;
+
+struct clk_lookup {
+       struct list_head        node;
+       const char              *dev_id;
+       const char              *con_id;
+       struct clk              *clk;
+};
+
+struct clk_lookup *clkdev_alloc(struct clk *clk, const char *con_id,
+       const char *dev_fmt, ...);
+
+void clkdev_add(struct clk_lookup *cl);
+void clkdev_drop(struct clk_lookup *cl);
+
+void clkdev_add_table(struct clk_lookup *, size_t);
+int clk_add_alias(const char *, const char *, char *, struct device *);
+
+#endif
index 7605fdd1eb65de1fffd5f1bf5b47428e16475133..e3d8bf26e5eb229a9ca2959fc5ea2b1638238988 100644 (file)
@@ -61,13 +61,31 @@ union cnt32_to_63 {
  *
  * 2) this code must not be preempted for a duration longer than the
  *    32-bit counter half period minus the longest period between two
- *    calls to this code.
+ *    calls to this code;
  *
  * Those requirements ensure proper update to the state bit in memory.
  * This is usually not a problem in practice, but if it is then a kernel
  * timer should be scheduled to manage for this code to be executed often
  * enough.
  *
+ * And finally:
+ *
+ * 3) the cnt_lo argument must be seen as a globally incrementing value,
+ *    meaning that it should be a direct reference to the counter data which
+ *    can be evaluated according to a specific ordering within the macro,
+ *    and not the result of a previous evaluation stored in a variable.
+ *
+ * For example, this is wrong:
+ *
+ *     u32 partial = get_hw_count();
+ *     u64 full = cnt32_to_63(partial);
+ *     return full;
+ *
+ * This is fine:
+ *
+ *     u64 full = cnt32_to_63(get_hw_count());
+ *     return full;
+ *
  * Note that the top bit (bit 63) in the returned value should be considered
  * as garbage.  It is not cleared here because callers are likely to use a
  * multiplier on the returned value which can get rid of the top bit
index 0026f267da20d6e9f1a0dc5343b978c1e5f0b6f1..088cd4ace4ef756c542cffc66e9b8a42f5ad1b38 100644 (file)
@@ -20,7 +20,14 @@ extern ssize_t copy_oldmem_page(unsigned long, char *, size_t,
 #define vmcore_elf_check_arch_cross(x) 0
 #endif
 
-#define vmcore_elf_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+/*
+ * Architecture code can redefine this if there are any special checks
+ * needed for 64-bit ELF vmcores. In case of 32-bit only architecture,
+ * this can be set to zero.
+ */
+#ifndef vmcore_elf64_check_arch
+#define vmcore_elf64_check_arch(x) (elf_check_arch(x) || vmcore_elf_check_arch_cross(x))
+#endif
 
 /*
  * is_kdump_kernel() checks whether this kernel is booting after a panic of
index 9d8688b92d8b02c46980f9a4397e4b2d0c313413..8cd00ad98d3773a4afa44e5e7ad6eaac184e6d71 100644 (file)
@@ -824,6 +824,8 @@ enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie);
 #ifdef CONFIG_DMA_ENGINE
 enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx);
 void dma_issue_pending_all(void);
+struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
+void dma_release_channel(struct dma_chan *chan);
 #else
 static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx)
 {
@@ -831,7 +833,14 @@ static inline enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descript
 }
 static inline void dma_issue_pending_all(void)
 {
-       do { } while (0);
+}
+static inline struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask,
+                                             dma_filter_fn fn, void *fn_param)
+{
+       return NULL;
+}
+static inline void dma_release_channel(struct dma_chan *chan)
+{
 }
 #endif
 
@@ -842,8 +851,6 @@ void dma_async_device_unregister(struct dma_device *device);
 void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
 struct dma_chan *dma_find_channel(enum dma_transaction_type tx_type);
 #define dma_request_channel(mask, x, y) __dma_request_channel(&(mask), x, y)
-struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, void *fn_param);
-void dma_release_channel(struct dma_chan *chan);
 
 /* --- Helper iov-locking functions --- */
 
index 0f0121467fc4b8cf261cbb06a9ff6347b3596474..6c6133f76e163c88041c4a13a4b091ef6ccf13ac 100644 (file)
                                 FAN_ALL_PERM_EVENTS |\
                                 FAN_Q_OVERFLOW)
 
-#define FANOTIFY_METADATA_VERSION      2
+#define FANOTIFY_METADATA_VERSION      3
 
 struct fanotify_event_metadata {
        __u32 event_len;
-       __u32 vers;
+       __u8 vers;
+       __u8 reserved;
+       __u16 metadata_len;
        __aligned_u64 mask;
        __s32 fd;
        __s32 pid;
@@ -96,11 +98,13 @@ struct fanotify_event_metadata {
 struct fanotify_response {
        __s32 fd;
        __u32 response;
-} __attribute__ ((packed));
+};
 
 /* Legit userspace responses to a _PERM event */
 #define FAN_ALLOW      0x01
 #define FAN_DENY       0x02
+/* No fd set in event */
+#define FAN_NOFD       -1
 
 /* Helper functions to deal with fanotify_event_metadata buffers */
 #define FAN_EVENT_METADATA_LEN (sizeof(struct fanotify_event_metadata))
index 5c185fa27089f03b4e9194445ee7bfd842f125c6..b10bcdeaef768b2b0b123c4a6c862b3f5f6c0694 100644 (file)
@@ -235,9 +235,6 @@ static inline void fsnotify_open(struct file *file)
        if (S_ISDIR(inode->i_mode))
                mask |= FS_ISDIR;
 
-       /* FMODE_NONOTIFY must never be set from user */
-       file->f_mode &= ~FMODE_NONOTIFY;
-
        fsnotify_parent(path, NULL, mask);
        fsnotify(inode, mask, path, FSNOTIFY_EVENT_PATH, NULL, 0);
 }
index 0a68f924f06fcf3f6f75727f382971bc16e5608f..7380763595d30accb255728f45682550cc540d63 100644 (file)
@@ -166,7 +166,7 @@ struct fsnotify_group {
                        struct mutex access_mutex;
                        struct list_head access_list;
                        wait_queue_head_t access_waitq;
-                       bool bypass_perm; /* protected by access_mutex */
+                       atomic_t bypass_perm;
 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
                        int f_flags;
                        unsigned int max_marks;
index a8af21d42bc146cc6f6ee186894e623b01a884ff..9777668883be6aa18a309b6388616fe08ee900ea 100644 (file)
@@ -104,8 +104,10 @@ struct input_keymap_entry {
 #define EVIOCGREP              _IOR('E', 0x03, unsigned int[2])        /* get repeat settings */
 #define EVIOCSREP              _IOW('E', 0x03, unsigned int[2])        /* set repeat settings */
 
-#define EVIOCGKEYCODE          _IOR('E', 0x04, struct input_keymap_entry)      /* get keycode */
-#define EVIOCSKEYCODE          _IOW('E', 0x04, struct input_keymap_entry)      /* set keycode */
+#define EVIOCGKEYCODE          _IOR('E', 0x04, unsigned int[2])        /* get keycode */
+#define EVIOCGKEYCODE_V2       _IOR('E', 0x04, struct input_keymap_entry)
+#define EVIOCSKEYCODE          _IOW('E', 0x04, unsigned int[2])        /* set keycode */
+#define EVIOCSKEYCODE_V2       _IOW('E', 0x04, struct input_keymap_entry)
 
 #define EVIOCGNAME(len)                _IOC(_IOC_READ, 'E', 0x06, len)         /* get device name */
 #define EVIOCGPHYS(len)                _IOC(_IOC_READ, 'E', 0x07, len)         /* get physical location */
index d377ea815d453b9ec232f22efc5503f5d456b0cf..e9bb22cba764139cc69f3faa1e16f11cc0e05eb2 100644 (file)
@@ -112,7 +112,6 @@ struct resource_list {
 /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
 extern struct resource ioport_resource;
 extern struct resource iomem_resource;
-extern int resource_alloc_from_bottom;
 
 extern struct resource *request_resource_conflict(struct resource *root, struct resource *new);
 extern int request_resource(struct resource *root, struct resource *new);
@@ -124,6 +123,7 @@ extern void reserve_region_with_split(struct resource *root,
 extern struct resource *insert_resource_conflict(struct resource *parent, struct resource *new);
 extern int insert_resource(struct resource *parent, struct resource *new);
 extern void insert_resource_expand_to_fit(struct resource *root, struct resource *new);
+extern void arch_remove_reservations(struct resource *avail);
 extern int allocate_resource(struct resource *root, struct resource *new,
                             resource_size_t size, resource_size_t min,
                             resource_size_t max, resource_size_t align,
index 685ea65eb803fddf1c47ee3e420fe3056278685b..ce0775aa64c376b8980a6af70ef59f14d19f1ba0 100644 (file)
@@ -81,16 +81,41 @@ struct kthread_work {
 #define DEFINE_KTHREAD_WORK(work, fn)                                  \
        struct kthread_work work = KTHREAD_WORK_INIT(work, fn)
 
-static inline void init_kthread_worker(struct kthread_worker *worker)
-{
-       *worker = (struct kthread_worker)KTHREAD_WORKER_INIT(*worker);
-}
-
-static inline void init_kthread_work(struct kthread_work *work,
-                                    kthread_work_func_t fn)
-{
-       *work = (struct kthread_work)KTHREAD_WORK_INIT(*work, fn);
-}
+/*
+ * kthread_worker.lock and kthread_work.done need their own lockdep class
+ * keys if they are defined on stack with lockdep enabled.  Use the
+ * following macros when defining them on stack.
+ */
+#ifdef CONFIG_LOCKDEP
+# define KTHREAD_WORKER_INIT_ONSTACK(worker)                           \
+       ({ init_kthread_worker(&worker); worker; })
+# define DEFINE_KTHREAD_WORKER_ONSTACK(worker)                         \
+       struct kthread_worker worker = KTHREAD_WORKER_INIT_ONSTACK(worker)
+# define KTHREAD_WORK_INIT_ONSTACK(work, fn)                           \
+       ({ init_kthread_work((&work), fn); work; })
+# define DEFINE_KTHREAD_WORK_ONSTACK(work, fn)                         \
+       struct kthread_work work = KTHREAD_WORK_INIT_ONSTACK(work, fn)
+#else
+# define DEFINE_KTHREAD_WORKER_ONSTACK(worker) DEFINE_KTHREAD_WORKER(worker)
+# define DEFINE_KTHREAD_WORK_ONSTACK(work, fn) DEFINE_KTHREAD_WORK(work, fn)
+#endif
+
+extern void __init_kthread_worker(struct kthread_worker *worker,
+                       const char *name, struct lock_class_key *key);
+
+#define init_kthread_worker(worker)                                    \
+       do {                                                            \
+               static struct lock_class_key __key;                     \
+               __init_kthread_worker((worker), "("#worker")->lock", &__key); \
+       } while (0)
+
+#define init_kthread_work(work, fn)                                    \
+       do {                                                            \
+               memset((work), 0, sizeof(struct kthread_work));         \
+               INIT_LIST_HEAD(&(work)->node);                          \
+               (work)->func = (fn);                                    \
+               init_waitqueue_head(&(work)->done);                     \
+       } while (0)
 
 int kthread_worker_fn(void *worker_ptr);
 
index 123566912d7312f276bf975cd1a48c97b2ffa830..e2b9e63afa68b53f45fdc60c1a3f76cf0f338705 100644 (file)
@@ -70,7 +70,7 @@ struct nlmsghdr {
    Check               NLM_F_EXCL
  */
 
-#define NLMSG_ALIGNTO  4
+#define NLMSG_ALIGNTO  4U
 #define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
 #define NLMSG_HDRLEN    ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
 #define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
index de2c41758e29e20d6a709303f21a6d8242696fa0..4f1279e105ee143e4317219b3cb093bc8bbdd954 100644 (file)
@@ -887,6 +887,7 @@ struct perf_cpu_context {
        int                             exclusive;
        struct list_head                rotation_list;
        int                             jiffies_interval;
+       struct pmu                      *active_pmu;
 };
 
 struct perf_output_handle {
index 3ec2358f8692d11027e6af927402fcbc0f039da2..d19f1cca7f740a9150f516c98e5c9deecfd271ae 100644 (file)
@@ -77,7 +77,8 @@ static inline void device_set_run_wake(struct device *dev, bool enable)
 
 static inline bool pm_runtime_suspended(struct device *dev)
 {
-       return dev->power.runtime_status == RPM_SUSPENDED;
+       return dev->power.runtime_status == RPM_SUSPENDED
+               && !dev->power.disable_depth;
 }
 
 static inline void pm_runtime_mark_last_busy(struct device *dev)
index 2c79e921a68baeb9d5afa9b0deaa731232685ed5..223874538b33208e3c5ff11710f3161d58b4aef2 100644 (file)
@@ -143,7 +143,7 @@ extern unsigned long nr_iowait_cpu(int cpu);
 extern unsigned long this_cpu_load(void);
 
 
-extern void calc_global_load(void);
+extern void calc_global_load(unsigned long ticks);
 
 extern unsigned long get_parent_ip(unsigned long addr);
 
index 942e3873690190addb45bdde24a069a812f3b8b8..eba52a100533349461c1965f996074c187eaab08 100644 (file)
@@ -96,16 +96,21 @@ static inline bool ssb_gige_must_flush_posted_writes(struct pci_dev *pdev)
        return 0;
 }
 
-extern char * nvram_get(const char *name);
+#ifdef CONFIG_BCM47XX
+#include <asm/mach-bcm47xx/nvram.h>
 /* Get the device MAC address */
 static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
 {
-#ifdef CONFIG_BCM47XX
-       char *res = nvram_get("et0macaddr");
-       if (res)
-               memcpy(macaddr, res, 6);
-#endif
+       char buf[20];
+       if (nvram_getenv("et0macaddr", buf, sizeof(buf)) < 0)
+               return;
+       nvram_parse_macaddr(buf, macaddr);
 }
+#else
+static inline void ssb_gige_get_macaddr(struct pci_dev *pdev, u8 *macaddr)
+{
+}
+#endif
 
 extern int ssb_gige_pcibios_plat_dev_init(struct ssb_device *sdev,
                                          struct pci_dev *pdev);
index 341dddb55090853430c39bd76a081bc2125c8fe5..2466e550a41d40beefe6aa1b5ed4560ac076bc29 100644 (file)
@@ -33,7 +33,7 @@
  */
 
 
-#define TASKSTATS_VERSION      7
+#define TASKSTATS_VERSION      8
 #define TS_COMM_LEN            32      /* should be >= TASK_COMM_LEN
                                         * in linux/sched.h */
 
@@ -188,6 +188,7 @@ enum {
        TASKSTATS_TYPE_STATS,           /* taskstats structure */
        TASKSTATS_TYPE_AGGR_PID,        /* contains pid + stats */
        TASKSTATS_TYPE_AGGR_TGID,       /* contains tgid + stats */
+       TASKSTATS_TYPE_NULL,            /* contains nothing */
        __TASKSTATS_TYPE_MAX,
 };
 
index 2498bb9fe002a4bafee70389e70c57b842ede507..c9a6abd972a142e7aea4129da8a8e5b9bc64b6ce 100644 (file)
@@ -3,9 +3,9 @@
 
 #include <linux/kernel.h>
 
-struct __una_u16 { u16 x __attribute__((packed)); };
-struct __una_u32 { u32 x __attribute__((packed)); };
-struct __una_u64 { u64 x __attribute__((packed)); };
+struct __una_u16 { u16 x; } __attribute__((packed));
+struct __una_u32 { u32 x; } __attribute__((packed));
+struct __una_u64 { u64 x; } __attribute__((packed));
 
 static inline u16 __get_unaligned_cpu16(const void *p)
 {
index 7a9f76ecbbbd8298339c5f88a92238af144e0a68..ac7ce00f39cff70a1fdd70e9b32dfb4c4a62c46f 100644 (file)
@@ -161,7 +161,7 @@ extern struct list_head saa7146_devices;
 extern struct mutex saa7146_devices_lock;
 int saa7146_register_extension(struct saa7146_extension*);
 int saa7146_unregister_extension(struct saa7146_extension*);
-struct saa7146_format* format_by_fourcc(struct saa7146_dev *dev, int fourcc);
+struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc);
 int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt);
 void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt);
 int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length );
index 6648036b728d7e32beb09fb91757931265780823..b16f307d471a2df59fd622cba1b338e42503ec16 100644 (file)
@@ -51,6 +51,8 @@ struct v4l2_device {
                        unsigned int notification, void *arg);
        /* The control handler. May be NULL. */
        struct v4l2_ctrl_handler *ctrl_handler;
+       /* BKL replacement mutex. Temporary solution only. */
+       struct mutex ioctl_lock;
 };
 
 /* Initialize v4l2_dev and make dev->driver_data point to v4l2_dev.
index a1c4d417dfa205e8d5c2cf1d4f9d6bbd7a6ec419..60739c5a23ae3e30e943b55dc45cd53289720db4 100644 (file)
@@ -32,7 +32,4 @@
 #define WM8775_AIN3 4
 #define WM8775_AIN4 8
 
-/* subdev group ID */
-#define WM8775_GID (1 << 0)
-
 #endif
index 0ac3fb5e0973460f3046cdf1f00a0e1114a13dff..bb08692a20b08841ead94acce78c9ead82293d94 100644 (file)
@@ -49,7 +49,6 @@ struct flowi {
        __u8    proto;
        __u8    flags;
 #define FLOWI_FLAG_ANYSRC 0x01
-#define FLOWI_FLAG_MATCH_ANY_IIF 0x02
        union {
                struct {
                        __be16  sport;
index 278312c95f9600bd863fa0dc76c52a7c048a9d19..2ab926860cd855b6ec7861a998d19612624980e6 100644 (file)
@@ -164,5 +164,15 @@ static inline int ipv6_unicast_destination(struct sk_buff *skb)
        return rt->rt6i_flags & RTF_LOCAL;
 }
 
+int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
+
+static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
+{
+       struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
+
+       return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ?
+              skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
+}
+
 #endif
 #endif
index 9fdf982d1286a95c02a73bae4131746f05de9343..365359b24177a1a52310679293c43dba7b97533f 100644 (file)
@@ -2024,8 +2024,8 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
  *
  * This function may not be called in IRQ context. Calls to this function
  * for a single hardware must be synchronized against each other. Calls
- * to this function and ieee80211_tx_status_irqsafe() may not be mixed
- * for a single hardware.
+ * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe()
+ * may not be mixed for a single hardware.
  *
  * @hw: the hardware the frame was transmitted by
  * @skb: the frame that was transmitted, owned by mac80211 after this call
@@ -2033,14 +2033,34 @@ static inline void ieee80211_rx_ni(struct ieee80211_hw *hw,
 void ieee80211_tx_status(struct ieee80211_hw *hw,
                         struct sk_buff *skb);
 
+/**
+ * ieee80211_tx_status_ni - transmit status callback (in process context)
+ *
+ * Like ieee80211_tx_status() but can be called in process context.
+ *
+ * Calls to this function, ieee80211_tx_status() and
+ * ieee80211_tx_status_irqsafe() may not be mixed
+ * for a single hardware.
+ *
+ * @hw: the hardware the frame was transmitted by
+ * @skb: the frame that was transmitted, owned by mac80211 after this call
+ */
+static inline void ieee80211_tx_status_ni(struct ieee80211_hw *hw,
+                                         struct sk_buff *skb)
+{
+       local_bh_disable();
+       ieee80211_tx_status(hw, skb);
+       local_bh_enable();
+}
+
 /**
  * ieee80211_tx_status_irqsafe - IRQ-safe transmit status callback
  *
  * Like ieee80211_tx_status() but can be called in IRQ context
  * (internally defers to a tasklet.)
  *
- * Calls to this function and ieee80211_tx_status() may not be mixed for a
- * single hardware.
+ * Calls to this function, ieee80211_tx_status() and
+ * ieee80211_tx_status_ni() may not be mixed for a single hardware.
  *
  * @hw: the hardware the frame was transmitted by
  * @skb: the frame that was transmitted, owned by mac80211 after this call
index dd3031aed9d52e7c3bf5d2c6ad464dbdc23477c0..9fcc680ab6b9d1f4de4d15583275efe7acf66975 100644 (file)
@@ -323,7 +323,9 @@ static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer)
 static inline int tcf_valid_offset(const struct sk_buff *skb,
                                   const unsigned char *ptr, const int len)
 {
-       return unlikely((ptr + len) < skb_tail_pointer(skb) && ptr > skb->head);
+       return likely((ptr + len) <= skb_tail_pointer(skb) &&
+                     ptr >= skb->head &&
+                     (ptr <= (ptr + len)));
 }
 
 #ifdef CONFIG_NET_CLS_IND
index ea1f8a83160df419e986d51ad864a14a215cbea3..79f34e2b752f61479a4b8aae9bc29551cff3b7d0 100644 (file)
@@ -610,11 +610,7 @@ static inline struct sk_buff *skb_act_clone(struct sk_buff *skb, gfp_t gfp_mask,
 {
        struct sk_buff *n;
 
-       if ((action == TC_ACT_STOLEN || action == TC_ACT_QUEUED) &&
-           !skb_shared(skb))
-               n = skb_get(skb);
-       else
-               n = skb_clone(skb, gfp_mask);
+       n = skb_clone(skb, gfp_mask);
 
        if (n) {
                n->tc_verd = SET_TC_VERD(n->tc_verd, 0);
index 659d968d95c54afe6df51c3289a0d2d6fb5b34ed..7d3f7ce239b5b831c66b20b7df61e593384604b2 100644 (file)
@@ -754,6 +754,7 @@ struct proto {
        void                    (*unhash)(struct sock *sk);
        void                    (*rehash)(struct sock *sk);
        int                     (*get_port)(struct sock *sk, unsigned short snum);
+       void                    (*clear_sk)(struct sock *sk, int size);
 
        /* Keeping track of sockets in use */
 #ifdef CONFIG_PROC_FS
@@ -852,6 +853,8 @@ static inline void __sk_prot_rehash(struct sock *sk)
        sk->sk_prot->hash(sk);
 }
 
+void sk_prot_clear_portaddr_nulls(struct sock *sk, int size);
+
 /* About 10 seconds */
 #define SOCK_DESTROY_TIME (10*HZ)
 
index 830aaec9c7d5e0cb8df39af760791b5335772768..2b54bef33b55c65f8fda4ebf3129db3453c8f53d 100644 (file)
@@ -93,7 +93,7 @@ no_match:
  *
  * Returns the matching dev_t on success or 0 on failure.
  */
-static dev_t __init devt_from_partuuid(char *uuid_str)
+static dev_t devt_from_partuuid(char *uuid_str)
 {
        dev_t res = 0;
        struct device *dev = NULL;
index 3b159c5991b7561bdba253eeb479f91622a35fb9..5447dc7defa95b8f0e13acb80b45487df7dc2e73 100644 (file)
@@ -273,6 +273,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 
        setup_thread_stack(tsk, orig);
        clear_user_return_notifier(tsk);
+       clear_tsk_need_resched(tsk);
        stackend = end_of_stack(tsk);
        *stackend = STACK_END_MAGIC;    /* for overflow detection */
 
index 2dc3786349d1723394c25e512b9b570bcf5a4f7e..ca61bbdd44b2e11acad4d866ab31224a5a5cab16 100644 (file)
@@ -265,6 +265,17 @@ int kthreadd(void *unused)
        return 0;
 }
 
+void __init_kthread_worker(struct kthread_worker *worker,
+                               const char *name,
+                               struct lock_class_key *key)
+{
+       spin_lock_init(&worker->lock);
+       lockdep_set_class_and_name(&worker->lock, key, name);
+       INIT_LIST_HEAD(&worker->work_list);
+       worker->task = NULL;
+}
+EXPORT_SYMBOL_GPL(__init_kthread_worker);
+
 /**
  * kthread_worker_fn - kthread function to process kthread_worker
  * @worker_ptr: pointer to initialized kthread_worker
index eac7e3364335a7a3f94d902e69b9ed4eac4df74a..2870feee81dd7a046703645c9ec50022d4339f39 100644 (file)
@@ -3824,6 +3824,8 @@ static void perf_event_task_event(struct perf_task_event *task_event)
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_task_ctx(&cpuctx->ctx, task_event);
 
                ctx = task_event->task_ctx;
@@ -3959,6 +3961,8 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event)
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_comm_ctx(&cpuctx->ctx, comm_event);
 
                ctxn = pmu->task_ctx_nr;
@@ -4144,6 +4148,8 @@ got_name:
        rcu_read_lock();
        list_for_each_entry_rcu(pmu, &pmus, entry) {
                cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
+               if (cpuctx->active_pmu != pmu)
+                       goto next;
                perf_event_mmap_ctx(&cpuctx->ctx, mmap_event,
                                        vma->vm_flags & VM_EXEC);
 
@@ -4713,7 +4719,7 @@ static int perf_swevent_init(struct perf_event *event)
                break;
        }
 
-       if (event_id > PERF_COUNT_SW_MAX)
+       if (event_id >= PERF_COUNT_SW_MAX)
                return -ENOENT;
 
        if (!event->parent) {
@@ -5145,20 +5151,36 @@ static void *find_pmu_context(int ctxn)
        return NULL;
 }
 
-static void free_pmu_context(void * __percpu cpu_context)
+static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu)
 {
-       struct pmu *pmu;
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               struct perf_cpu_context *cpuctx;
+
+               cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
+
+               if (cpuctx->active_pmu == old_pmu)
+                       cpuctx->active_pmu = pmu;
+       }
+}
+
+static void free_pmu_context(struct pmu *pmu)
+{
+       struct pmu *i;
 
        mutex_lock(&pmus_lock);
        /*
         * Like a real lame refcount.
         */
-       list_for_each_entry(pmu, &pmus, entry) {
-               if (pmu->pmu_cpu_context == cpu_context)
+       list_for_each_entry(i, &pmus, entry) {
+               if (i->pmu_cpu_context == pmu->pmu_cpu_context) {
+                       update_pmu_context(i, pmu);
                        goto out;
+               }
        }
 
-       free_percpu(cpu_context);
+       free_percpu(pmu->pmu_cpu_context);
 out:
        mutex_unlock(&pmus_lock);
 }
@@ -5190,6 +5212,7 @@ int perf_pmu_register(struct pmu *pmu)
                cpuctx->ctx.pmu = pmu;
                cpuctx->jiffies_interval = 1;
                INIT_LIST_HEAD(&cpuctx->rotation_list);
+               cpuctx->active_pmu = pmu;
        }
 
 got_cpu_context:
@@ -5241,7 +5264,7 @@ void perf_pmu_unregister(struct pmu *pmu)
        synchronize_rcu();
 
        free_percpu(pmu->pmu_disable_count);
-       free_pmu_context(pmu->pmu_cpu_context);
+       free_pmu_context(pmu);
 }
 
 struct pmu *perf_init_event(struct perf_event *event)
index baf667bb2794c6880a834e060fd3a32943c80d68..8c7e4832b9be0f8e031fb07645f6ad8e955c0318 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "power.h"
 
-#define HIBERNATE_SIG  "LINHIB0001"
+#define HIBERNATE_SIG  "S1SUSPEND"
 
 /*
  *     The swap map is a data structure used for keeping track of each page
index 1b2ea31e6bd8c0eca7eaaf985bc84337a1e750d0..c36c3b9e8a84f59ad5894a1e2d04c7252b656ebe 100644 (file)
@@ -137,7 +137,7 @@ static int snapshot_release(struct inode *inode, struct file *filp)
        free_all_swap_pages(data->swap);
        if (data->frozen)
                thaw_processes();
-       pm_notifier_call_chain(data->mode == O_WRONLY ?
+       pm_notifier_call_chain(data->mode == O_RDONLY ?
                        PM_POST_HIBERNATION : PM_POST_RESTORE);
        atomic_inc(&snapshot_device_available);
 
index 9fad33efd0db50b3269572f598a1ce418731153c..798e2fae2a069645c13853f4b658dada92af8f66 100644 (file)
@@ -40,23 +40,6 @@ EXPORT_SYMBOL(iomem_resource);
 
 static DEFINE_RWLOCK(resource_lock);
 
-/*
- * By default, we allocate free space bottom-up.  The architecture can request
- * top-down by clearing this flag.  The user can override the architecture's
- * choice with the "resource_alloc_from_bottom" kernel boot option, but that
- * should only be a debugging tool.
- */
-int resource_alloc_from_bottom = 1;
-
-static __init int setup_alloc_from_bottom(char *s)
-{
-       printk(KERN_INFO
-              "resource: allocating from bottom-up; please report a bug\n");
-       resource_alloc_from_bottom = 1;
-       return 0;
-}
-early_param("resource_alloc_from_bottom", setup_alloc_from_bottom);
-
 static void *r_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct resource *p = v;
@@ -374,6 +357,10 @@ int __weak page_is_ram(unsigned long pfn)
        return walk_system_ram_range(pfn, 1, NULL, __is_ram) == 1;
 }
 
+void __weak arch_remove_reservations(struct resource *avail)
+{
+}
+
 static resource_size_t simple_align_resource(void *data,
                                             const struct resource *avail,
                                             resource_size_t size,
@@ -396,75 +383,8 @@ static bool resource_contains(struct resource *res1, struct resource *res2)
        return res1->start <= res2->start && res1->end >= res2->end;
 }
 
-/*
- * Find the resource before "child" in the sibling list of "root" children.
- */
-static struct resource *find_sibling_prev(struct resource *root, struct resource *child)
-{
-       struct resource *this;
-
-       for (this = root->child; this; this = this->sibling)
-               if (this->sibling == child)
-                       return this;
-
-       return NULL;
-}
-
 /*
  * Find empty slot in the resource tree given range and alignment.
- * This version allocates from the end of the root resource first.
- */
-static int find_resource_from_top(struct resource *root, struct resource *new,
-                                 resource_size_t size, resource_size_t min,
-                                 resource_size_t max, resource_size_t align,
-                                 resource_size_t (*alignf)(void *,
-                                                  const struct resource *,
-                                                  resource_size_t,
-                                                  resource_size_t),
-                                 void *alignf_data)
-{
-       struct resource *this;
-       struct resource tmp, avail, alloc;
-
-       tmp.start = root->end;
-       tmp.end = root->end;
-
-       this = find_sibling_prev(root, NULL);
-       for (;;) {
-               if (this) {
-                       if (this->end < root->end)
-                               tmp.start = this->end + 1;
-               } else
-                       tmp.start = root->start;
-
-               resource_clip(&tmp, min, max);
-
-               /* Check for overflow after ALIGN() */
-               avail = *new;
-               avail.start = ALIGN(tmp.start, align);
-               avail.end = tmp.end;
-               if (avail.start >= tmp.start) {
-                       alloc.start = alignf(alignf_data, &avail, size, align);
-                       alloc.end = alloc.start + size - 1;
-                       if (resource_contains(&avail, &alloc)) {
-                               new->start = alloc.start;
-                               new->end = alloc.end;
-                               return 0;
-                       }
-               }
-
-               if (!this || this->start == root->start)
-                       break;
-
-               tmp.end = this->start - 1;
-               this = find_sibling_prev(root, this);
-       }
-       return -EBUSY;
-}
-
-/*
- * Find empty slot in the resource tree given range and alignment.
- * This version allocates from the beginning of the root resource first.
  */
 static int find_resource(struct resource *root, struct resource *new,
                         resource_size_t size, resource_size_t min,
@@ -478,23 +398,24 @@ static int find_resource(struct resource *root, struct resource *new,
        struct resource *this = root->child;
        struct resource tmp = *new, avail, alloc;
 
+       tmp.flags = new->flags;
        tmp.start = root->start;
        /*
-        * Skip past an allocated resource that starts at 0, since the
-        * assignment of this->start - 1 to tmp->end below would cause an
-        * underflow.
+        * Skip past an allocated resource that starts at 0, since the assignment
+        * of this->start - 1 to tmp->end below would cause an underflow.
         */
        if (this && this->start == 0) {
                tmp.start = this->end + 1;
                this = this->sibling;
        }
-       for (;;) {
+       for(;;) {
                if (this)
                        tmp.end = this->start - 1;
                else
                        tmp.end = root->end;
 
                resource_clip(&tmp, min, max);
+               arch_remove_reservations(&tmp);
 
                /* Check for overflow after ALIGN() */
                avail = *new;
@@ -509,10 +430,8 @@ static int find_resource(struct resource *root, struct resource *new,
                                return 0;
                        }
                }
-
                if (!this)
                        break;
-
                tmp.start = this->end + 1;
                this = this->sibling;
        }
@@ -545,10 +464,7 @@ int allocate_resource(struct resource *root, struct resource *new,
                alignf = simple_align_resource;
 
        write_lock(&resource_lock);
-       if (resource_alloc_from_bottom)
-               err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
-       else
-               err = find_resource_from_top(root, new, size, min, max, align, alignf, alignf_data);
+       err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
        if (err >= 0 && __request_resource(root, new))
                err = -EBUSY;
        write_unlock(&resource_lock);
index dc91a4d09ac3b71a3c347187ff2a1691c952cebd..297d1a0eedb0e68d8b9327f530ba477c93b1222e 100644 (file)
@@ -636,22 +636,18 @@ static inline struct task_group *task_group(struct task_struct *p)
 
 #endif /* CONFIG_CGROUP_SCHED */
 
-static u64 irq_time_cpu(int cpu);
-static void sched_irq_time_avg_update(struct rq *rq, u64 irq_time);
+static void update_rq_clock_task(struct rq *rq, s64 delta);
 
-inline void update_rq_clock(struct rq *rq)
+static void update_rq_clock(struct rq *rq)
 {
-       if (!rq->skip_clock_update) {
-               int cpu = cpu_of(rq);
-               u64 irq_time;
+       s64 delta;
 
-               rq->clock = sched_clock_cpu(cpu);
-               irq_time = irq_time_cpu(cpu);
-               if (rq->clock - irq_time > rq->clock_task)
-                       rq->clock_task = rq->clock - irq_time;
+       if (rq->skip_clock_update)
+               return;
 
-               sched_irq_time_avg_update(rq, irq_time);
-       }
+       delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
+       rq->clock += delta;
+       update_rq_clock_task(rq, delta);
 }
 
 /*
@@ -1924,10 +1920,9 @@ static void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
  * They are read and saved off onto struct rq in update_rq_clock().
  * This may result in other CPU reading this CPU's irq time and can
  * race with irq/account_system_vtime on this CPU. We would either get old
- * or new value (or semi updated value on 32 bit) with a side effect of
- * accounting a slice of irq time to wrong task when irq is in progress
- * while we read rq->clock. That is a worthy compromise in place of having
- * locks on each irq in account_system_time.
+ * or new value with a side effect of accounting a slice of irq time to wrong
+ * task when irq is in progress while we read rq->clock. That is a worthy
+ * compromise in place of having locks on each irq in account_system_time.
  */
 static DEFINE_PER_CPU(u64, cpu_hardirq_time);
 static DEFINE_PER_CPU(u64, cpu_softirq_time);
@@ -1945,19 +1940,58 @@ void disable_sched_clock_irqtime(void)
        sched_clock_irqtime = 0;
 }
 
-static u64 irq_time_cpu(int cpu)
+#ifndef CONFIG_64BIT
+static DEFINE_PER_CPU(seqcount_t, irq_time_seq);
+
+static inline void irq_time_write_begin(void)
 {
-       if (!sched_clock_irqtime)
-               return 0;
+       __this_cpu_inc(irq_time_seq.sequence);
+       smp_wmb();
+}
+
+static inline void irq_time_write_end(void)
+{
+       smp_wmb();
+       __this_cpu_inc(irq_time_seq.sequence);
+}
+
+static inline u64 irq_time_read(int cpu)
+{
+       u64 irq_time;
+       unsigned seq;
 
+       do {
+               seq = read_seqcount_begin(&per_cpu(irq_time_seq, cpu));
+               irq_time = per_cpu(cpu_softirq_time, cpu) +
+                          per_cpu(cpu_hardirq_time, cpu);
+       } while (read_seqcount_retry(&per_cpu(irq_time_seq, cpu), seq));
+
+       return irq_time;
+}
+#else /* CONFIG_64BIT */
+static inline void irq_time_write_begin(void)
+{
+}
+
+static inline void irq_time_write_end(void)
+{
+}
+
+static inline u64 irq_time_read(int cpu)
+{
        return per_cpu(cpu_softirq_time, cpu) + per_cpu(cpu_hardirq_time, cpu);
 }
+#endif /* CONFIG_64BIT */
 
+/*
+ * Called before incrementing preempt_count on {soft,}irq_enter
+ * and before decrementing preempt_count on {soft,}irq_exit.
+ */
 void account_system_vtime(struct task_struct *curr)
 {
        unsigned long flags;
+       s64 delta;
        int cpu;
-       u64 now, delta;
 
        if (!sched_clock_irqtime)
                return;
@@ -1965,9 +1999,10 @@ void account_system_vtime(struct task_struct *curr)
        local_irq_save(flags);
 
        cpu = smp_processor_id();
-       now = sched_clock_cpu(cpu);
-       delta = now - per_cpu(irq_start_time, cpu);
-       per_cpu(irq_start_time, cpu) = now;
+       delta = sched_clock_cpu(cpu) - __this_cpu_read(irq_start_time);
+       __this_cpu_add(irq_start_time, delta);
+
+       irq_time_write_begin();
        /*
         * We do not account for softirq time from ksoftirqd here.
         * We want to continue accounting softirq time to ksoftirqd thread
@@ -1975,33 +2010,55 @@ void account_system_vtime(struct task_struct *curr)
         * that do not consume any time, but still wants to run.
         */
        if (hardirq_count())
-               per_cpu(cpu_hardirq_time, cpu) += delta;
+               __this_cpu_add(cpu_hardirq_time, delta);
        else if (in_serving_softirq() && !(curr->flags & PF_KSOFTIRQD))
-               per_cpu(cpu_softirq_time, cpu) += delta;
+               __this_cpu_add(cpu_softirq_time, delta);
 
+       irq_time_write_end();
        local_irq_restore(flags);
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
 
-static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time)
+static void update_rq_clock_task(struct rq *rq, s64 delta)
 {
-       if (sched_clock_irqtime && sched_feat(NONIRQ_POWER)) {
-               u64 delta_irq = curr_irq_time - rq->prev_irq_time;
-               rq->prev_irq_time = curr_irq_time;
-               sched_rt_avg_update(rq, delta_irq);
-       }
+       s64 irq_delta;
+
+       irq_delta = irq_time_read(cpu_of(rq)) - rq->prev_irq_time;
+
+       /*
+        * Since irq_time is only updated on {soft,}irq_exit, we might run into
+        * this case when a previous update_rq_clock() happened inside a
+        * {soft,}irq region.
+        *
+        * When this happens, we stop ->clock_task and only update the
+        * prev_irq_time stamp to account for the part that fit, so that a next
+        * update will consume the rest. This ensures ->clock_task is
+        * monotonic.
+        *
+        * It does however cause some slight miss-attribution of {soft,}irq
+        * time, a more accurate solution would be to update the irq_time using
+        * the current rq->clock timestamp, except that would require using
+        * atomic ops.
+        */
+       if (irq_delta > delta)
+               irq_delta = delta;
+
+       rq->prev_irq_time += irq_delta;
+       delta -= irq_delta;
+       rq->clock_task += delta;
+
+       if (irq_delta && sched_feat(NONIRQ_POWER))
+               sched_rt_avg_update(rq, irq_delta);
 }
 
-#else
+#else /* CONFIG_IRQ_TIME_ACCOUNTING */
 
-static u64 irq_time_cpu(int cpu)
+static void update_rq_clock_task(struct rq *rq, s64 delta)
 {
-       return 0;
+       rq->clock_task += delta;
 }
 
-static void sched_irq_time_avg_update(struct rq *rq, u64 curr_irq_time) { }
-
-#endif
+#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
 
 #include "sched_idletask.c"
 #include "sched_fair.c"
@@ -2129,7 +2186,7 @@ static void check_preempt_curr(struct rq *rq, struct task_struct *p, int flags)
         * A queue event has occurred, and we're going to schedule.  In
         * this case, we can save a useless back to back clock update.
         */
-       if (test_tsk_need_resched(rq->curr))
+       if (rq->curr->se.on_rq && test_tsk_need_resched(rq->curr))
                rq->skip_clock_update = 1;
 }
 
@@ -3119,6 +3176,15 @@ static long calc_load_fold_active(struct rq *this_rq)
        return delta;
 }
 
+static unsigned long
+calc_load(unsigned long load, unsigned long exp, unsigned long active)
+{
+       load *= exp;
+       load += active * (FIXED_1 - exp);
+       load += 1UL << (FSHIFT - 1);
+       return load >> FSHIFT;
+}
+
 #ifdef CONFIG_NO_HZ
 /*
  * For NO_HZ we delay the active fold to the next LOAD_FREQ update.
@@ -3148,6 +3214,128 @@ static long calc_load_fold_idle(void)
 
        return delta;
 }
+
+/**
+ * fixed_power_int - compute: x^n, in O(log n) time
+ *
+ * @x:         base of the power
+ * @frac_bits: fractional bits of @x
+ * @n:         power to raise @x to.
+ *
+ * By exploiting the relation between the definition of the natural power
+ * function: x^n := x*x*...*x (x multiplied by itself for n times), and
+ * the binary encoding of numbers used by computers: n := \Sum n_i * 2^i,
+ * (where: n_i \elem {0, 1}, the binary vector representing n),
+ * we find: x^n := x^(\Sum n_i * 2^i) := \Prod x^(n_i * 2^i), which is
+ * of course trivially computable in O(log_2 n), the length of our binary
+ * vector.
+ */
+static unsigned long
+fixed_power_int(unsigned long x, unsigned int frac_bits, unsigned int n)
+{
+       unsigned long result = 1UL << frac_bits;
+
+       if (n) for (;;) {
+               if (n & 1) {
+                       result *= x;
+                       result += 1UL << (frac_bits - 1);
+                       result >>= frac_bits;
+               }
+               n >>= 1;
+               if (!n)
+                       break;
+               x *= x;
+               x += 1UL << (frac_bits - 1);
+               x >>= frac_bits;
+       }
+
+       return result;
+}
+
+/*
+ * a1 = a0 * e + a * (1 - e)
+ *
+ * a2 = a1 * e + a * (1 - e)
+ *    = (a0 * e + a * (1 - e)) * e + a * (1 - e)
+ *    = a0 * e^2 + a * (1 - e) * (1 + e)
+ *
+ * a3 = a2 * e + a * (1 - e)
+ *    = (a0 * e^2 + a * (1 - e) * (1 + e)) * e + a * (1 - e)
+ *    = a0 * e^3 + a * (1 - e) * (1 + e + e^2)
+ *
+ *  ...
+ *
+ * an = a0 * e^n + a * (1 - e) * (1 + e + ... + e^n-1) [1]
+ *    = a0 * e^n + a * (1 - e) * (1 - e^n)/(1 - e)
+ *    = a0 * e^n + a * (1 - e^n)
+ *
+ * [1] application of the geometric series:
+ *
+ *              n         1 - x^(n+1)
+ *     S_n := \Sum x^i = -------------
+ *             i=0          1 - x
+ */
+static unsigned long
+calc_load_n(unsigned long load, unsigned long exp,
+           unsigned long active, unsigned int n)
+{
+
+       return calc_load(load, fixed_power_int(exp, FSHIFT, n), active);
+}
+
+/*
+ * NO_HZ can leave us missing all per-cpu ticks calling
+ * calc_load_account_active(), but since an idle CPU folds its delta into
+ * calc_load_tasks_idle per calc_load_account_idle(), all we need to do is fold
+ * in the pending idle delta if our idle period crossed a load cycle boundary.
+ *
+ * Once we've updated the global active value, we need to apply the exponential
+ * weights adjusted to the number of cycles missed.
+ */
+static void calc_global_nohz(unsigned long ticks)
+{
+       long delta, active, n;
+
+       if (time_before(jiffies, calc_load_update))
+               return;
+
+       /*
+        * If we crossed a calc_load_update boundary, make sure to fold
+        * any pending idle changes, the respective CPUs might have
+        * missed the tick driven calc_load_account_active() update
+        * due to NO_HZ.
+        */
+       delta = calc_load_fold_idle();
+       if (delta)
+               atomic_long_add(delta, &calc_load_tasks);
+
+       /*
+        * If we were idle for multiple load cycles, apply them.
+        */
+       if (ticks >= LOAD_FREQ) {
+               n = ticks / LOAD_FREQ;
+
+               active = atomic_long_read(&calc_load_tasks);
+               active = active > 0 ? active * FIXED_1 : 0;
+
+               avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n);
+               avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n);
+               avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n);
+
+               calc_load_update += n * LOAD_FREQ;
+       }
+
+       /*
+        * Its possible the remainder of the above division also crosses
+        * a LOAD_FREQ period, the regular check in calc_global_load()
+        * which comes after this will take care of that.
+        *
+        * Consider us being 11 ticks before a cycle completion, and us
+        * sleeping for 4*LOAD_FREQ + 22 ticks, then the above code will
+        * age us 4 cycles, and the test in calc_global_load() will
+        * pick up the final one.
+        */
+}
 #else
 static void calc_load_account_idle(struct rq *this_rq)
 {
@@ -3157,6 +3345,10 @@ static inline long calc_load_fold_idle(void)
 {
        return 0;
 }
+
+static void calc_global_nohz(unsigned long ticks)
+{
+}
 #endif
 
 /**
@@ -3174,24 +3366,17 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift)
        loads[2] = (avenrun[2] + offset) << shift;
 }
 
-static unsigned long
-calc_load(unsigned long load, unsigned long exp, unsigned long active)
-{
-       load *= exp;
-       load += active * (FIXED_1 - exp);
-       return load >> FSHIFT;
-}
-
 /*
  * calc_load - update the avenrun load estimates 10 ticks after the
  * CPUs have updated calc_load_tasks.
  */
-void calc_global_load(void)
+void calc_global_load(unsigned long ticks)
 {
-       unsigned long upd = calc_load_update + 10;
        long active;
 
-       if (time_before(jiffies, upd))
+       calc_global_nohz(ticks);
+
+       if (time_before(jiffies, calc_load_update + 10))
                return;
 
        active = atomic_long_read(&calc_load_tasks);
@@ -3845,7 +4030,6 @@ static void put_prev_task(struct rq *rq, struct task_struct *prev)
 {
        if (prev->se.on_rq)
                update_rq_clock(rq);
-       rq->skip_clock_update = 0;
        prev->sched_class->put_prev_task(rq, prev);
 }
 
@@ -3903,7 +4087,6 @@ need_resched_nonpreemptible:
                hrtick_clear(rq);
 
        raw_spin_lock_irq(&rq->lock);
-       clear_tsk_need_resched(prev);
 
        switch_count = &prev->nivcsw;
        if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
@@ -3935,6 +4118,8 @@ need_resched_nonpreemptible:
 
        put_prev_task(rq, prev);
        next = pick_next_task(rq);
+       clear_tsk_need_resched(prev);
+       rq->skip_clock_update = 0;
 
        if (likely(prev != next)) {
                sched_info_switch(prev, next);
index c8231fb1570831d78215ab9967958a1663424ed0..3308fd7f1b52f170e4da5dd7e26749aca652ef1b 100644 (file)
@@ -349,25 +349,47 @@ static int parse(struct nlattr *na, struct cpumask *mask)
        return ret;
 }
 
+#ifdef CONFIG_IA64
+#define TASKSTATS_NEEDS_PADDING 1
+#endif
+
 static struct taskstats *mk_reply(struct sk_buff *skb, int type, u32 pid)
 {
        struct nlattr *na, *ret;
        int aggr;
 
-       /* If we don't pad, we end up with alignment on a 4 byte boundary.
-        * This causes lots of runtime warnings on systems requiring 8 byte
-        * alignment */
-       u32 pids[2] = { pid, 0 };
-       int pid_size = ALIGN(sizeof(pid), sizeof(long));
-
        aggr = (type == TASKSTATS_TYPE_PID)
                        ? TASKSTATS_TYPE_AGGR_PID
                        : TASKSTATS_TYPE_AGGR_TGID;
 
+       /*
+        * The taskstats structure is internally aligned on 8 byte
+        * boundaries but the layout of the aggregrate reply, with
+        * two NLA headers and the pid (each 4 bytes), actually
+        * force the entire structure to be unaligned. This causes
+        * the kernel to issue unaligned access warnings on some
+        * architectures like ia64. Unfortunately, some software out there
+        * doesn't properly unroll the NLA packet and assumes that the start
+        * of the taskstats structure will always be 20 bytes from the start
+        * of the netlink payload. Aligning the start of the taskstats
+        * structure breaks this software, which we don't want. So, for now
+        * the alignment only happens on architectures that require it
+        * and those users will have to update to fixed versions of those
+        * packages. Space is reserved in the packet only when needed.
+        * This ifdef should be removed in several years e.g. 2012 once
+        * we can be confident that fixed versions are installed on most
+        * systems. We add the padding before the aggregate since the
+        * aggregate is already a defined type.
+        */
+#ifdef TASKSTATS_NEEDS_PADDING
+       if (nla_put(skb, TASKSTATS_TYPE_NULL, 0, NULL) < 0)
+               goto err;
+#endif
        na = nla_nest_start(skb, aggr);
        if (!na)
                goto err;
-       if (nla_put(skb, type, pid_size, pids) < 0)
+
+       if (nla_put(skb, type, sizeof(pid), &pid) < 0)
                goto err;
        ret = nla_reserve(skb, TASKSTATS_TYPE_STATS, sizeof(struct taskstats));
        if (!ret)
@@ -456,6 +478,18 @@ out:
        return rc;
 }
 
+static size_t taskstats_packet_size(void)
+{
+       size_t size;
+
+       size = nla_total_size(sizeof(u32)) +
+               nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
+#ifdef TASKSTATS_NEEDS_PADDING
+       size += nla_total_size(0); /* Padding for alignment */
+#endif
+       return size;
+}
+
 static int cmd_attr_pid(struct genl_info *info)
 {
        struct taskstats *stats;
@@ -464,8 +498,7 @@ static int cmd_attr_pid(struct genl_info *info)
        u32 pid;
        int rc;
 
-       size = nla_total_size(sizeof(u32)) +
-               nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
+       size = taskstats_packet_size();
 
        rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);
        if (rc < 0)
@@ -494,8 +527,7 @@ static int cmd_attr_tgid(struct genl_info *info)
        u32 tgid;
        int rc;
 
-       size = nla_total_size(sizeof(u32)) +
-               nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
+       size = taskstats_packet_size();
 
        rc = prepare_reply(info, TASKSTATS_CMD_NEW, &rep_skb, size);
        if (rc < 0)
@@ -570,8 +602,7 @@ void taskstats_exit(struct task_struct *tsk, int group_dead)
        /*
         * Size includes space for nested attributes
         */
-       size = nla_total_size(sizeof(u32)) +
-               nla_total_size(sizeof(struct taskstats)) + nla_total_size(0);
+       size = taskstats_packet_size();
 
        is_thread_group = !!taskstats_tgid_alloc(tsk);
        if (is_thread_group) {
index c18d7efa1b4b10b0146466094016d74a69702c30..df140cd3ea473f36f8b7fc293ac5b79a916614f2 100644 (file)
@@ -152,6 +152,7 @@ clocks_calc_mult_shift(u32 *mult, u32 *shift, u32 from, u32 to, u32 minsec)
         */
        for (sft = 32; sft > 0; sft--) {
                tmp = (u64) to << sft;
+               tmp += from / 2;
                do_div(tmp, from);
                if ((tmp >> sftacc) == 0)
                        break;
index 68a9ae7679b717f6eb4782ce5114ad405dec5a4c..353b9227c2ecfe11793a17b0a41f534ebdbd14f8 100644 (file)
@@ -1252,6 +1252,12 @@ unsigned long get_next_timer_interrupt(unsigned long now)
        struct tvec_base *base = __get_cpu_var(tvec_bases);
        unsigned long expires;
 
+       /*
+        * Pretend that there is no timer pending if the cpu is offline.
+        * Possible pending timers will be migrated later to an active cpu.
+        */
+       if (cpu_is_offline(smp_processor_id()))
+               return now + NEXT_TIMER_MAX_DELTA;
        spin_lock(&base->lock);
        if (time_before_eq(base->next_timer, base->timer_jiffies))
                base->next_timer = __next_timer_interrupt(base);
@@ -1319,7 +1325,7 @@ void do_timer(unsigned long ticks)
 {
        jiffies_64 += ticks;
        update_wall_time();
-       calc_global_load();
+       calc_global_load(ticks);
 }
 
 #ifdef __ARCH_WANT_SYS_ALARM
index 9ed509a015d81a69cd452b3697658dd7fde9cb71..bd1c35a4fbccf31c0531f0667545011f704c561f 100644 (file)
@@ -3853,6 +3853,13 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
 
                /* Need to copy one event at a time */
                do {
+                       /* We need the size of one event, because
+                        * rb_advance_reader only advances by one event,
+                        * whereas rb_event_ts_length may include the size of
+                        * one or two events.
+                        * We have already ensured there's enough space if this
+                        * is a time extend. */
+                       size = rb_event_length(event);
                        memcpy(bpage->data + pos, rpage->data + rpos, size);
 
                        len -= size;
@@ -3867,7 +3874,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer,
                        event = rb_reader_event(cpu_buffer);
                        /* Always keep the time extend and data together */
                        size = rb_event_ts_length(event);
-               } while (len > size);
+               } while (len >= size);
 
                /* update bpage */
                local_set(&bpage->commit, pos);
index c380612273bf75d683ddebcf5e7863b30bece806..f8cf959bad456dead3a5dec2fdd1a21e384f22bb 100644 (file)
@@ -2338,11 +2338,19 @@ tracing_write_stub(struct file *filp, const char __user *ubuf,
        return count;
 }
 
+static loff_t tracing_seek(struct file *file, loff_t offset, int origin)
+{
+       if (file->f_mode & FMODE_READ)
+               return seq_lseek(file, offset, origin);
+       else
+               return 0;
+}
+
 static const struct file_operations tracing_fops = {
        .open           = tracing_open,
        .read           = seq_read,
        .write          = tracing_write_stub,
-       .llseek         = seq_lseek,
+       .llseek         = tracing_seek,
        .release        = tracing_release,
 };
 
index 2c7d8d5914b188be65c36a686a81fba7eed07d8c..5c598ca781df4bf6f907043ed1d43f98b3b7ef58 100644 (file)
@@ -158,6 +158,7 @@ struct user_struct *alloc_uid(struct user_namespace *ns, uid_t uid)
                spin_lock_irq(&uidhash_lock);
                up = uid_hash_find(uid, hashent);
                if (up) {
+                       put_user_ns(ns);
                        key_put(new->uid_keyring);
                        key_put(new->session_keyring);
                        kmem_cache_free(uid_cachep, new);
index 6e3c41a4024c1cc66be01218e2c37498498f2469..5b082156cd2146fcf0971568d8eb28cb371b3627 100644 (file)
@@ -364,7 +364,8 @@ static int watchdog_nmi_enable(int cpu)
                goto out_save;
        }
 
-       printk(KERN_ERR "NMI watchdog failed to create perf event on cpu%i: %p\n", cpu, event);
+       printk(KERN_ERR "NMI watchdog disabled for cpu%i: unable to create perf event: %ld\n",
+              cpu, PTR_ERR(event));
        return PTR_ERR(event);
 
        /* success path */
index 4d709ee5901370842534224a9f81e7d13943e196..1a8894eadf7275fc2a41f002cadaca4f86684cbf 100644 (file)
@@ -279,7 +279,6 @@ static unsigned long isolate_migratepages(struct zone *zone,
                /* Successfully isolated */
                del_page_from_lru_list(zone, page, page_lru(page));
                list_add(&page->lru, migratelist);
-               mem_cgroup_del_lru(page);
                cc->nr_migratepages++;
 
                /* Avoid isolating too much */
index 7a22b41292115f78dc039ebf5e271090dc5a8f9d..00bb8a64d028f945d50346c2332c6d4b54373621 100644 (file)
@@ -1925,19 +1925,18 @@ again:
 
                rcu_read_lock();
                p = rcu_dereference(mm->owner);
-               VM_BUG_ON(!p);
                /*
-                * because we don't have task_lock(), "p" can exit while
-                * we're here. In that case, "mem" can point to root
-                * cgroup but never be NULL. (and task_struct itself is freed
-                * by RCU, cgroup itself is RCU safe.) Then, we have small
-                * risk here to get wrong cgroup. But such kind of mis-account
-                * by race always happens because we don't have cgroup_mutex().
-                * It's overkill and we allow that small race, here.
+                * Because we don't have task_lock(), "p" can exit.
+                * In that case, "mem" can point to root or p can be NULL with
+                * race with swapoff. Then, we have small risk of mis-accouning.
+                * But such kind of mis-account by race always happens because
+                * we don't have cgroup_mutex(). It's overkill and we allo that
+                * small race, here.
+                * (*) swapoff at el will charge against mm-struct not against
+                * task-struct. So, mm->owner can be NULL.
                 */
                mem = mem_cgroup_from_task(p);
-               VM_BUG_ON(!mem);
-               if (mem_cgroup_is_root(mem)) {
+               if (!mem || mem_cgroup_is_root(mem)) {
                        rcu_read_unlock();
                        goto done;
                }
index fe5a3c6a54260f2ae9999fbaabe03082a818982f..6ae8a66a704575764ecf068c3f9a02bcc0a14575 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/hugetlb.h>
 #include <linux/gfp.h>
 
+#include <asm/tlbflush.h>
+
 #include "internal.h"
 
 #define lru_to_page(_head) (list_entry((_head)->prev, struct page, lru))
index 27a9ac58851678d30c7c477d00a857cf2f63bc35..ef4045d010d5f37631c3ad2f9de0e824e1de65a7 100644 (file)
@@ -10,7 +10,7 @@
  *  Copyright (c) 2000-2003 David McCullough <davidm@snapgear.com>
  *  Copyright (c) 2000-2001 D Jeff Dionne <jeff@uClinux.org>
  *  Copyright (c) 2002      Greg Ungerer <gerg@snapgear.com>
- *  Copyright (c) 2007-2009 Paul Mundt <lethal@linux-sh.org>
+ *  Copyright (c) 2007-2010 Paul Mundt <lethal@linux-sh.org>
  */
 
 #include <linux/module.h>
@@ -328,6 +328,7 @@ void *vmalloc_node(unsigned long size, int node)
 {
        return vmalloc(size);
 }
+EXPORT_SYMBOL(vmalloc_node);
 
 /**
  * vzalloc_node - allocate memory on a specific node with zero fill
@@ -440,6 +441,31 @@ void  __attribute__((weak)) vmalloc_sync_all(void)
 {
 }
 
+/**
+ *     alloc_vm_area - allocate a range of kernel address space
+ *     @size:          size of the area
+ *
+ *     Returns:        NULL on failure, vm_struct on success
+ *
+ *     This function reserves a range of kernel address space, and
+ *     allocates pagetables to map that range.  No actual mappings
+ *     are created.  If the kernel address space is not shared
+ *     between processes, it syncs the pagetable across all
+ *     processes.
+ */
+struct vm_struct *alloc_vm_area(size_t size)
+{
+       BUG();
+       return NULL;
+}
+EXPORT_SYMBOL_GPL(alloc_vm_area);
+
+void free_vm_area(struct vm_struct *area)
+{
+       BUG();
+}
+EXPORT_SYMBOL_GPL(free_vm_area);
+
 int vm_insert_page(struct vm_area_struct *vma, unsigned long addr,
                   struct page *page)
 {
index b840afa89761ce0d83690ff963385399246fa6d8..b4edfe7ce06c1bf5f6d692235eac4e07f9068490 100644 (file)
@@ -563,7 +563,7 @@ static void balance_dirty_pages(struct address_space *mapping,
                                break;          /* We've done our duty */
                }
                trace_wbc_balance_dirty_wait(&wbc, bdi);
-               __set_current_state(TASK_INTERRUPTIBLE);
+               __set_current_state(TASK_UNINTERRUPTIBLE);
                io_schedule_timeout(pause);
 
                /*
index efe816856a9d777b284f8bf25cc7548154f374d6..02ba91230b99269f45beea6387c165e042800347 100644 (file)
@@ -1268,7 +1268,7 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
 
        /* we're done parsing the input, undefine BUG macro and dump config */
 #undef PCPU_SETUP_BUG_ON
-       pcpu_dump_alloc_info(KERN_INFO, ai);
+       pcpu_dump_alloc_info(KERN_DEBUG, ai);
 
        pcpu_nr_groups = ai->nr_groups;
        pcpu_group_offsets = group_offsets;
index fa642aa652bdba0d4b0b3f47c77dc9e55571c19f..432a9a633e8d8da4ddcabdb1a9a3cef1a55a3253 100644 (file)
@@ -311,6 +311,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d)
        d->state      = BT_OPEN;
        d->flags      = 0;
        d->mscex      = 0;
+       d->sec_level  = BT_SECURITY_LOW;
        d->mtu        = RFCOMM_DEFAULT_MTU;
        d->v24_sig    = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV;
 
index eb5b256ffc8801ff7e187c64ee3dde5da268f570..543b3262d002cdca0213348b4878c364622394b1 100644 (file)
@@ -437,7 +437,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br,
        ip6h = ipv6_hdr(skb);
 
        *(__force __be32 *)ip6h = htonl(0x60000000);
-       ip6h->payload_len = 8 + sizeof(*mldq);
+       ip6h->payload_len = htons(8 + sizeof(*mldq));
        ip6h->nexthdr = IPPROTO_HOPOPTS;
        ip6h->hop_limit = 1;
        ipv6_addr_set(&ip6h->saddr, 0, 0, 0, 0);
@@ -1430,7 +1430,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
                                 struct net_bridge_port *port,
                                 struct sk_buff *skb)
 {
-       struct sk_buff *skb2 = skb;
+       struct sk_buff *skb2;
        struct ipv6hdr *ip6h;
        struct icmp6hdr *icmp6h;
        u8 nexthdr;
@@ -1469,15 +1469,15 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
        if (!skb2)
                return -ENOMEM;
 
+       err = -EINVAL;
+       if (!pskb_may_pull(skb2, offset + sizeof(struct icmp6hdr)))
+               goto out;
+
        len -= offset - skb_network_offset(skb2);
 
        __skb_pull(skb2, offset);
        skb_reset_transport_header(skb2);
 
-       err = -EINVAL;
-       if (!pskb_may_pull(skb2, sizeof(*icmp6h)))
-               goto out;
-
        icmp6h = icmp6_hdr(skb2);
 
        switch (icmp6h->icmp6_type) {
@@ -1516,7 +1516,12 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
        switch (icmp6h->icmp6_type) {
        case ICMPV6_MGM_REPORT:
            {
-               struct mld_msg *mld = (struct mld_msg *)icmp6h;
+               struct mld_msg *mld;
+               if (!pskb_may_pull(skb2, sizeof(*mld))) {
+                       err = -EINVAL;
+                       goto out;
+               }
+               mld = (struct mld_msg *)skb_transport_header(skb2);
                BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;
                err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
                break;
@@ -1529,15 +1534,18 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
                break;
        case ICMPV6_MGM_REDUCTION:
            {
-               struct mld_msg *mld = (struct mld_msg *)icmp6h;
+               struct mld_msg *mld;
+               if (!pskb_may_pull(skb2, sizeof(*mld))) {
+                       err = -EINVAL;
+                       goto out;
+               }
+               mld = (struct mld_msg *)skb_transport_header(skb2);
                br_ip6_multicast_leave_group(br, port, &mld->mld_mca);
            }
        }
 
 out:
-       __skb_push(skb2, offset);
-       if (skb2 != skb)
-               kfree_skb(skb2);
+       kfree_skb(skb2);
        return err;
 }
 #endif
index 35cf27087b561d6e9955fd75b4b03213a6e9e8d8..e3d7aefa91811d8945d9283d5de7ede9b168da34 100644 (file)
@@ -50,6 +50,8 @@ static void br_send_bpdu(struct net_bridge_port *p,
 
        llc_mac_hdr_init(skb, p->dev->dev_addr, p->br->group_addr);
 
+       skb_reset_mac_header(skb);
+
        NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_OUT, skb, NULL, skb->dev,
                dev_queue_xmit);
 }
index 6faa8256e10ca22d6fb0b2005d74c5c5580a404d..9d5e8accfab1d73f25e8a00ae45523a400b820ce 100644 (file)
@@ -125,7 +125,7 @@ struct bcm_sock {
        struct list_head tx_ops;
        unsigned long dropped_usr_msgs;
        struct proc_dir_entry *bcm_proc_read;
-       char procname [20]; /* pointer printed in ASCII with \0 */
+       char procname [32]; /* inode number in decimal with \0 */
 };
 
 static inline struct bcm_sock *bcm_sk(const struct sock *sk)
@@ -1521,7 +1521,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len,
 
        if (proc_dir) {
                /* unique socket address as filename */
-               sprintf(bo->procname, "%p", sock);
+               sprintf(bo->procname, "%lu", sock_i_ino(sk));
                bo->bcm_proc_read = proc_create_data(bo->procname, 0644,
                                                     proc_dir,
                                                     &bcm_proc_fops, sk);
index 1c7a2ec4f3cc81ee608821ddf589fc0b27db4dcc..b6ff4a1519ab664c43d9bff871dc95d8efb52daa 100644 (file)
@@ -97,11 +97,9 @@ struct workqueue_struct *ceph_msgr_wq;
 int ceph_msgr_init(void)
 {
        ceph_msgr_wq = create_workqueue("ceph-msgr");
-       if (IS_ERR(ceph_msgr_wq)) {
-               int ret = PTR_ERR(ceph_msgr_wq);
-               pr_err("msgr_init failed to create workqueue: %d\n", ret);
-               ceph_msgr_wq = NULL;
-               return ret;
+       if (!ceph_msgr_wq) {
+               pr_err("msgr_init failed to create workqueue\n");
+               return -ENOMEM;
        }
        return 0;
 }
index ac34feeb2b3ab2202e02aeab2a0367f29ac6a2b2..1a040e64c69f23545f98e282bae934b3ed33baa9 100644 (file)
@@ -13,7 +13,7 @@
  * build a vector of user pages
  */
 struct page **ceph_get_direct_page_vector(const char __user *data,
-                                         int num_pages)
+                                         int num_pages, bool write_page)
 {
        struct page **pages;
        int rc;
@@ -24,24 +24,27 @@ struct page **ceph_get_direct_page_vector(const char __user *data,
 
        down_read(&current->mm->mmap_sem);
        rc = get_user_pages(current, current->mm, (unsigned long)data,
-                           num_pages, 0, 0, pages, NULL);
+                           num_pages, write_page, 0, pages, NULL);
        up_read(&current->mm->mmap_sem);
-       if (rc < 0)
+       if (rc < num_pages)
                goto fail;
        return pages;
 
 fail:
-       kfree(pages);
+       ceph_put_page_vector(pages, rc > 0 ? rc : 0, false);
        return ERR_PTR(rc);
 }
 EXPORT_SYMBOL(ceph_get_direct_page_vector);
 
-void ceph_put_page_vector(struct page **pages, int num_pages)
+void ceph_put_page_vector(struct page **pages, int num_pages, bool dirty)
 {
        int i;
 
-       for (i = 0; i < num_pages; i++)
+       for (i = 0; i < num_pages; i++) {
+               if (dirty)
+                       set_page_dirty_lock(pages[i]);
                put_page(pages[i]);
+       }
        kfree(pages);
 }
 EXPORT_SYMBOL(ceph_put_page_vector);
index 82a4369ae15091520d99effdcbb36dec7b3bab42..a20e5d3bbfa017db76959cfd448962c134d5d309 100644 (file)
@@ -181,8 +181,7 @@ static int fib_rule_match(struct fib_rule *rule, struct fib_rules_ops *ops,
 {
        int ret = 0;
 
-       if (rule->iifindex && (rule->iifindex != fl->iif) &&
-           !(fl->flags & FLOWI_FLAG_MATCH_ANY_IIF))
+       if (rule->iifindex && (rule->iifindex != fl->iif))
                goto out;
 
        if (rule->oifindex && (rule->oifindex != fl->oif))
index fb6080111461546953b34979db77f5e2d516e060..e5af8d5d5b505d79e3102a0aa879ba3d3e17f82b 100644 (file)
@@ -1009,6 +1009,36 @@ static void sock_copy(struct sock *nsk, const struct sock *osk)
 #endif
 }
 
+/*
+ * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes
+ * un-modified. Special care is taken when initializing object to zero.
+ */
+static inline void sk_prot_clear_nulls(struct sock *sk, int size)
+{
+       if (offsetof(struct sock, sk_node.next) != 0)
+               memset(sk, 0, offsetof(struct sock, sk_node.next));
+       memset(&sk->sk_node.pprev, 0,
+              size - offsetof(struct sock, sk_node.pprev));
+}
+
+void sk_prot_clear_portaddr_nulls(struct sock *sk, int size)
+{
+       unsigned long nulls1, nulls2;
+
+       nulls1 = offsetof(struct sock, __sk_common.skc_node.next);
+       nulls2 = offsetof(struct sock, __sk_common.skc_portaddr_node.next);
+       if (nulls1 > nulls2)
+               swap(nulls1, nulls2);
+
+       if (nulls1 != 0)
+               memset((char *)sk, 0, nulls1);
+       memset((char *)sk + nulls1 + sizeof(void *), 0,
+              nulls2 - nulls1 - sizeof(void *));
+       memset((char *)sk + nulls2 + sizeof(void *), 0,
+              size - nulls2 - sizeof(void *));
+}
+EXPORT_SYMBOL(sk_prot_clear_portaddr_nulls);
+
 static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
                int family)
 {
@@ -1021,19 +1051,12 @@ static struct sock *sk_prot_alloc(struct proto *prot, gfp_t priority,
                if (!sk)
                        return sk;
                if (priority & __GFP_ZERO) {
-                       /*
-                        * caches using SLAB_DESTROY_BY_RCU should let
-                        * sk_node.next un-modified. Special care is taken
-                        * when initializing object to zero.
-                        */
-                       if (offsetof(struct sock, sk_node.next) != 0)
-                               memset(sk, 0, offsetof(struct sock, sk_node.next));
-                       memset(&sk->sk_node.pprev, 0,
-                              prot->obj_size - offsetof(struct sock,
-                                                        sk_node.pprev));
+                       if (prot->clear_sk)
+                               prot->clear_sk(sk, prot->obj_size);
+                       else
+                               sk_prot_clear_nulls(sk, prot->obj_size);
                }
-       }
-       else
+       } else
                sk = kmalloc(prot->obj_size, priority);
 
        if (sk != NULL) {
index eb6f69a8f27aff4db2de494389dd7d9584b93ece..c19c1f739fbadc48d39a87c25c550f49de100db4 100644 (file)
@@ -163,13 +163,19 @@ struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref)
                                .daddr = addr
                        }
                },
-               .flags = FLOWI_FLAG_MATCH_ANY_IIF
        };
        struct fib_result res = { 0 };
        struct net_device *dev = NULL;
+       struct fib_table *local_table;
+
+#ifdef CONFIG_IP_MULTIPLE_TABLES
+       res.r = NULL;
+#endif
 
        rcu_read_lock();
-       if (fib_lookup(net, &fl, &res)) {
+       local_table = fib_get_table(net, RT_TABLE_LOCAL);
+       if (!local_table ||
+           fib_table_lookup(local_table, &fl, &res, FIB_LOOKUP_NOREF)) {
                rcu_read_unlock();
                return NULL;
        }
index 987bf9adb31833c19a0db04ce76060306d8e6994..93bfd95584f4656605eb963919de2d74b7c729f0 100644 (file)
@@ -2585,9 +2585,10 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
                        goto out;
 
                /* RACE: Check return value of inet_select_addr instead. */
-               if (rcu_dereference(dev_out->ip_ptr) == NULL)
-                       goto out;       /* Wrong error code */
-
+               if (!(dev_out->flags & IFF_UP) || !__in_dev_get_rcu(dev_out)) {
+                       err = -ENETUNREACH;
+                       goto out;
+               }
                if (ipv4_is_local_multicast(oldflp->fl4_dst) ||
                    ipv4_is_lbcast(oldflp->fl4_dst)) {
                        if (!fl.fl4_src)
@@ -2648,8 +2649,12 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
        }
 
        if (res.type == RTN_LOCAL) {
-               if (!fl.fl4_src)
-                       fl.fl4_src = fl.fl4_dst;
+               if (!fl.fl4_src) {
+                       if (res.fi->fib_prefsrc)
+                               fl.fl4_src = res.fi->fib_prefsrc;
+                       else
+                               fl.fl4_src = fl.fl4_dst;
+               }
                dev_out = net->loopback_dev;
                fl.oif = dev_out->ifindex;
                res.fi = NULL;
index e13da6de1fc79e26dc6d03b671e1becf9e6c8754..d978bb2f748b34d99efb0162e4e083a460275630 100644 (file)
@@ -2030,7 +2030,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
 get_req:
                        req = icsk->icsk_accept_queue.listen_opt->syn_table[st->sbucket];
                }
-               sk        = sk_next(st->syn_wait_sk);
+               sk        = sk_nulls_next(st->syn_wait_sk);
                st->state = TCP_SEQ_STATE_LISTENING;
                read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
        } else {
@@ -2039,7 +2039,7 @@ get_req:
                if (reqsk_queue_len(&icsk->icsk_accept_queue))
                        goto start_req;
                read_unlock_bh(&icsk->icsk_accept_queue.syn_wait_lock);
-               sk = sk_next(sk);
+               sk = sk_nulls_next(sk);
        }
 get_sk:
        sk_nulls_for_each_from(sk, node) {
index 5e0a3a582a59a05466468b244371dc5675bedc67..2d3ded4d078684298f9116f5c225f92b8908120e 100644 (file)
@@ -1899,6 +1899,7 @@ struct proto udp_prot = {
        .compat_setsockopt = compat_udp_setsockopt,
        .compat_getsockopt = compat_udp_getsockopt,
 #endif
+       .clear_sk          = sk_prot_clear_portaddr_nulls,
 };
 EXPORT_SYMBOL(udp_prot);
 
index ab76aa928fa98d6f1b8a8f6371d2b898ebdccb24..aee9963f7f5a497efc06429d3ab730e9f3efc999 100644 (file)
@@ -57,6 +57,7 @@ struct proto  udplite_prot = {
        .compat_setsockopt = compat_udp_setsockopt,
        .compat_getsockopt = compat_udp_getsockopt,
 #endif
+       .clear_sk          = sk_prot_clear_portaddr_nulls,
 };
 EXPORT_SYMBOL(udplite_prot);
 
index 93b7a933a7758254ed70ed849d333ad4d19114a7..848b355910424e75d42df6b9218eae3824ee213c 100644 (file)
@@ -2669,7 +2669,9 @@ static int addrconf_ifdown(struct net_device *dev, int how)
 
        ASSERT_RTNL();
 
-       rt6_ifdown(net, dev);
+       /* Flush routes if device is being removed or it is not loopback */
+       if (how || !(dev->flags & IFF_LOOPBACK))
+               rt6_ifdown(net, dev);
        neigh_ifdown(&nd_tbl, dev);
 
        idev = __in6_dev_get(dev);
index 99157b4cd56e2fa619939a17aa5b716680fc8799..94b5bf132b2e33a467f662b8c0e402a459f00a3d 100644 (file)
@@ -56,7 +56,7 @@
 #include <net/checksum.h>
 #include <linux/mroute6.h>
 
-static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
+int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *));
 
 int __ip6_local_out(struct sk_buff *skb)
 {
@@ -145,14 +145,6 @@ static int ip6_finish_output2(struct sk_buff *skb)
        return -EINVAL;
 }
 
-static inline int ip6_skb_dst_mtu(struct sk_buff *skb)
-{
-       struct ipv6_pinfo *np = skb->sk ? inet6_sk(skb->sk) : NULL;
-
-       return (np && np->pmtudisc == IPV6_PMTUDISC_PROBE) ?
-              skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb));
-}
-
 static int ip6_finish_output(struct sk_buff *skb)
 {
        if ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
@@ -601,7 +593,7 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
        return offset;
 }
 
-static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
+int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
 {
        struct sk_buff *frag;
        struct rt6_info *rt = (struct rt6_info*)skb_dst(skb);
index 96455ffb76fb8b92aa90c3a711aa6635d45b91fa..7659d6f16e6bae4b7e8a1701161181f627c0e41f 100644 (file)
@@ -1565,11 +1565,16 @@ static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr,
 {
        struct rt6_info *rt, *nrt;
        int allfrag = 0;
-
+again:
        rt = rt6_lookup(net, daddr, saddr, ifindex, 0);
        if (rt == NULL)
                return;
 
+       if (rt6_check_expired(rt)) {
+               ip6_del_rt(rt);
+               goto again;
+       }
+
        if (pmtu >= dst_mtu(&rt->dst))
                goto out;
 
index 91def93bec85060e7571218c20439cabd4ec824f..cd6cb7c3e5636e5911a36b5e1b4ebb4cb96b4be4 100644 (file)
@@ -1477,6 +1477,7 @@ struct proto udpv6_prot = {
        .compat_setsockopt = compat_udpv6_setsockopt,
        .compat_getsockopt = compat_udpv6_getsockopt,
 #endif
+       .clear_sk          = sk_prot_clear_portaddr_nulls,
 };
 
 static struct inet_protosw udpv6_protosw = {
index 5f48fadc27f7a62aa13632fc31bea73e1d1e6aec..986c4de5292eedf715b25b8bae98ee640917d97e 100644 (file)
@@ -55,6 +55,7 @@ struct proto udplitev6_prot = {
        .compat_setsockopt = compat_udpv6_setsockopt,
        .compat_getsockopt = compat_udpv6_getsockopt,
 #endif
+       .clear_sk          = sk_prot_clear_portaddr_nulls,
 };
 
 static struct inet_protosw udplite6_protosw = {
index 6434bd5ce0885ad20408a2f79eb198b8f30c269a..8e688b3de9abc62ec03c7dd90b33c951791c5587 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/netfilter_ipv6.h>
 #include <net/dst.h>
 #include <net/ipv6.h>
+#include <net/ip6_route.h>
 #include <net/xfrm.h>
 
 int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
@@ -88,8 +89,21 @@ static int xfrm6_output_finish(struct sk_buff *skb)
        return xfrm_output(skb);
 }
 
+static int __xfrm6_output(struct sk_buff *skb)
+{
+       struct dst_entry *dst = skb_dst(skb);
+       struct xfrm_state *x = dst->xfrm;
+
+       if ((x && x->props.mode == XFRM_MODE_TUNNEL) &&
+           ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
+               dst_allfrag(skb_dst(skb)))) {
+                       return ip6_fragment(skb, xfrm6_output_finish);
+       }
+       return xfrm6_output_finish(skb);
+}
+
 int xfrm6_output(struct sk_buff *skb)
 {
        return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL,
-                      skb_dst(skb)->dev, xfrm6_output_finish);
+                      skb_dst(skb)->dev, __xfrm6_output);
 }
index a6de3059746ddd3f3039d564f20acf394225e3ad..c9890e25cd4c9681b14f838976a97ed4db560ac7 100644 (file)
@@ -2280,6 +2280,16 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
 
        switch (optname) {
        case IRLMP_ENUMDEVICES:
+
+               /* Offset to first device entry */
+               offset = sizeof(struct irda_device_list) -
+                       sizeof(struct irda_device_info);
+
+               if (len < offset) {
+                       err = -EINVAL;
+                       goto out;
+               }
+
                /* Ask lmp for the current discovery log */
                discoveries = irlmp_get_discoveries(&list.len, self->mask.word,
                                                    self->nslots);
@@ -2290,15 +2300,9 @@ static int irda_getsockopt(struct socket *sock, int level, int optname,
                }
 
                /* Write total list length back to client */
-               if (copy_to_user(optval, &list,
-                                sizeof(struct irda_device_list) -
-                                sizeof(struct irda_device_info)))
+               if (copy_to_user(optval, &list, offset))
                        err = -EFAULT;
 
-               /* Offset to first device entry */
-               offset = sizeof(struct irda_device_list) -
-                       sizeof(struct irda_device_info);
-
                /* Copy the list itself - watch for overflow */
                if (list.len > 2048) {
                        err = -EINVAL;
index 239c4836a946601f27c69f965ae1a0935e71b434..077a93dd1671a841b9db85fe4cf6981aa90c1edf 100644 (file)
@@ -780,6 +780,9 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
        mutex_lock(&sdata->u.ibss.mtx);
 
+       if (!sdata->u.ibss.ssid_len)
+               goto mgmt_out; /* not ready to merge yet */
+
        switch (fc & IEEE80211_FCTL_STYPE) {
        case IEEE80211_STYPE_PROBE_REQ:
                ieee80211_rx_mgmt_probe_req(sdata, mgmt, skb->len);
@@ -797,6 +800,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                break;
        }
 
+ mgmt_out:
        mutex_unlock(&sdata->u.ibss.mtx);
 }
 
index 54fb4a0e76f03d835c6038cffeabf18874cb2d59..b01e467b76c69f15aa8de00434deca874b89ae48 100644 (file)
@@ -1788,9 +1788,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 
                        fwd_skb = skb_copy(skb, GFP_ATOMIC);
 
-                       if (!fwd_skb && net_ratelimit())
+                       if (!fwd_skb && net_ratelimit()) {
                                printk(KERN_DEBUG "%s: failed to clone mesh frame\n",
                                                   sdata->name);
+                               goto out;
+                       }
 
                        fwd_hdr =  (struct ieee80211_hdr *) fwd_skb->data;
                        memcpy(fwd_hdr->addr2, sdata->vif.addr, ETH_ALEN);
@@ -1828,6 +1830,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                }
        }
 
+ out:
        if (is_multicast_ether_addr(hdr->addr1) ||
            sdata->dev->flags & IFF_PROMISC)
                return RX_CONTINUE;
index ae344d1ba0560480665e1b939b15b058f5fddc4c..146097cb43a710d756ab997770faa812293ba85e 100644 (file)
@@ -1051,11 +1051,13 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_work *wk;
+       bool cleanup = false;
 
        mutex_lock(&local->mtx);
        list_for_each_entry(wk, &local->work_list, list) {
                if (wk->sdata != sdata)
                        continue;
+               cleanup = true;
                wk->type = IEEE80211_WORK_ABORT;
                wk->started = true;
                wk->timeout = jiffies;
@@ -1063,7 +1065,8 @@ void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata)
        mutex_unlock(&local->mtx);
 
        /* run cleanups etc. */
-       ieee80211_work_work(&local->work_work);
+       if (cleanup)
+               ieee80211_work_work(&local->work_work);
 
        mutex_lock(&local->mtx);
        list_for_each_entry(wk, &local->work_list, list) {
index 3cf478d012dd4f29b7a67f951c2cfa901b64248f..7150705f1d0b8b7aa12de87067928c25605ffbbb 100644 (file)
@@ -270,7 +270,6 @@ static unsigned int sfq_drop(struct Qdisc *sch)
                /* It is difficult to believe, but ALL THE SLOTS HAVE LENGTH 1. */
                d = q->next[q->tail];
                q->next[q->tail] = q->next[d];
-               q->allot[q->next[d]] += q->quantum;
                skb = q->qs[d].prev;
                len = qdisc_pkt_len(skb);
                __skb_unlink(skb, &q->qs[d]);
@@ -321,14 +320,13 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        sfq_inc(q, x);
        if (q->qs[x].qlen == 1) {               /* The flow is new */
                if (q->tail == SFQ_DEPTH) {     /* It is the first flow */
-                       q->tail = x;
                        q->next[x] = x;
-                       q->allot[x] = q->quantum;
                } else {
                        q->next[x] = q->next[q->tail];
                        q->next[q->tail] = x;
-                       q->tail = x;
                }
+               q->tail = x;
+               q->allot[x] = q->quantum;
        }
        if (++sch->q.qlen <= q->limit) {
                sch->bstats.bytes += qdisc_pkt_len(skb);
@@ -359,13 +357,13 @@ sfq_dequeue(struct Qdisc *sch)
 {
        struct sfq_sched_data *q = qdisc_priv(sch);
        struct sk_buff *skb;
-       sfq_index a, old_a;
+       sfq_index a, next_a;
 
        /* No active slots */
        if (q->tail == SFQ_DEPTH)
                return NULL;
 
-       a = old_a = q->next[q->tail];
+       a = q->next[q->tail];
 
        /* Grab packet */
        skb = __skb_dequeue(&q->qs[a]);
@@ -376,17 +374,15 @@ sfq_dequeue(struct Qdisc *sch)
        /* Is the slot empty? */
        if (q->qs[a].qlen == 0) {
                q->ht[q->hash[a]] = SFQ_DEPTH;
-               a = q->next[a];
-               if (a == old_a) {
+               next_a = q->next[a];
+               if (a == next_a) {
                        q->tail = SFQ_DEPTH;
                        return skb;
                }
-               q->next[q->tail] = a;
-               q->allot[a] += q->quantum;
+               q->next[q->tail] = next_a;
        } else if ((q->allot[a] -= qdisc_pkt_len(skb)) <= 0) {
-               q->tail = a;
-               a = q->next[a];
                q->allot[a] += q->quantum;
+               q->tail = a;
        }
        return skb;
 }
index 0b9ee34ad35ceb31ff764baf9cec73fba010f55b..fff0926b11112a8dd04d11e1e7f9ba378c40fcc3 100644 (file)
@@ -5053,7 +5053,7 @@ static int sctp_getsockopt_partial_delivery_point(struct sock *sk, int len,
        if (copy_to_user(optval, &val, len))
                return -EFAULT;
 
-       return -ENOTSUPP;
+       return 0;
 }
 
 /*
index b9d9aa18e6d62bbaa40c34cf7062c00c8bb15e35..5f77dcb8977e0632b5875167d5a652ef62f4be1c 100644 (file)
@@ -140,6 +140,20 @@ struct property *menu_add_prop(enum prop_type type, char *prompt, struct expr *e
                }
                if (current_entry->prompt && current_entry != &rootmenu)
                        prop_warn(prop, "prompt redefined");
+
+               /* Apply all upper menus' visibilities to actual prompts. */
+               if(type == P_PROMPT) {
+                       struct menu *menu = current_entry;
+
+                       while ((menu = menu->parent) != NULL) {
+                               if (!menu->visibility)
+                                       continue;
+                               prop->visible.expr
+                                       = expr_alloc_and(prop->visible.expr,
+                                                        menu->visibility);
+                       }
+               }
+
                current_entry->prompt = prop;
        }
        prop->text = prompt;
index f2f32eee2c5bbff3880b52be0769ca8a78cd171a..038b3d1e29814f789ec6728708c4f71858ef7234 100644 (file)
@@ -38,6 +38,7 @@ static void *ehdr_curr; /* current ElfXX_Ehdr *  for resource cleanup */
 static char gpfx;      /* prefix for global symbol name (sometimes '_') */
 static struct stat sb; /* Remember .st_size, etc. */
 static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
+static const char *altmcount;  /* alternate mcount symbol name */
 
 /* setjmp() return values */
 enum {
@@ -299,7 +300,9 @@ do_file(char const *const fname)
                fail_file();
        } break;
        case EM_386:     reltype = R_386_32;                   break;
-       case EM_ARM:     reltype = R_ARM_ABS32;                break;
+       case EM_ARM:     reltype = R_ARM_ABS32;
+                        altmcount = "__gnu_mcount_nc";
+                        break;
        case EM_IA_64:   reltype = R_IA64_IMM64;   gpfx = '_'; break;
        case EM_MIPS:    /* reltype: e_class    */ gpfx = '_'; break;
        case EM_PPC:     reltype = R_PPC_ADDR32;   gpfx = '_'; break;
@@ -357,7 +360,7 @@ do_file(char const *const fname)
 int
 main(int argc, char const *argv[])
 {
-       const char ftrace[] = "kernel/trace/ftrace.o";
+       const char ftrace[] = "/ftrace.o";
        int ftrace_size = sizeof(ftrace) - 1;
        int n_error = 0;  /* gcc-4.3.0 false positive complaint */
 
index 58e933a20544a2cd379446661d01f3755494bf97..baf187bee983c33b6323cfea1b8591ca963fc934 100644 (file)
@@ -119,7 +119,7 @@ static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM;
 
 static void fn_ELF_R_INFO(Elf_Rel *const rp, unsigned sym, unsigned type)
 {
-       rp->r_info = ELF_R_INFO(sym, type);
+       rp->r_info = _w(ELF_R_INFO(sym, type));
 }
 static void (*Elf_r_info)(Elf_Rel *const rp, unsigned sym, unsigned type) = fn_ELF_R_INFO;
 
@@ -275,11 +275,12 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,
                        Elf_Sym const *const symp =
                                &sym0[Elf_r_sym(relp)];
                        char const *symname = &str0[w(symp->st_name)];
+                       char const *mcount = '_' == gpfx ? "_mcount" : "mcount";
 
                        if ('.' == symname[0])
                                ++symname;  /* ppc64 hack */
-                       if (0 == strcmp((('_' == gpfx) ? "_mcount" : "mcount"),
-                                       symname))
+                       if (0 == strcmp(mcount, symname) ||
+                           (altmcount && 0 == strcmp(altmcount, symname)))
                                mcountsym = Elf_r_sym(relp);
                }
 
index 8509bb51293530fae488f60594199031cd16bf07..bbbe584d44943077a41b22684b5ecdbce18f532a 100755 (executable)
@@ -125,7 +125,9 @@ exuberant()
        -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \
        --extra=+f --c-kinds=-px                                \
        --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'                  \
-       --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/'
+       --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \
+       --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/'               \
+       --regex-c++='/^DEFINE_EVENT\(([^,)]*).*/trace_\1/'
 
        all_kconfigs | xargs $1 -a                              \
        --langdef=kconfig --language-force=kconfig              \
index aef8c0a923ab8e2276f97e1fe2aa61b7748e25e4..d661afbe474c2fce8f74907869be0a644c5789c9 100644 (file)
@@ -253,6 +253,8 @@ static int ima_lsm_rule_init(struct ima_measure_rule_entry *entry,
        result = security_filter_rule_init(entry->lsm[lsm_rule].type,
                                           Audit_equal, args,
                                           &entry->lsm[lsm_rule].rule);
+       if (!entry->lsm[lsm_rule].rule)
+               return -EINVAL;
        return result;
 }
 
index 0088dd8bf68a77b29637527733ff0b8985b8ecb7..0ea52d25a6bda8b3568fdb7752539403e93086b6 100644 (file)
@@ -403,7 +403,6 @@ link_check_failed:
        return ret;
 
 link_prealloc_failed:
-       up_write(&dest_keyring->sem);
        mutex_unlock(&user->cons_lock);
        kleave(" = %d [prelink]", ret);
        return ret;
index b75db8e9cc0f36fff03d0ecf1884b23b3bad724b..11446a1506dad244b2d11c447e6dc39e906427f1 100644 (file)
@@ -1070,8 +1070,10 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
                struct snd_pcm_hw_rule *new;
                unsigned int new_rules = constrs->rules_all + 16;
                new = kcalloc(new_rules, sizeof(*c), GFP_KERNEL);
-               if (!new)
+               if (!new) {
+                       va_end(args);
                        return -ENOMEM;
+               }
                if (constrs->rules) {
                        memcpy(new, constrs->rules,
                               constrs->rules_num * sizeof(*c));
@@ -1087,8 +1089,10 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
        c->private = private;
        k = 0;
        while (1) {
-               if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps)))
+               if (snd_BUG_ON(k >= ARRAY_SIZE(c->deps))) {
+                       va_end(args);
                        return -EINVAL;
+               }
                c->deps[k++] = dep;
                if (dep < 0)
                        break;
@@ -1097,7 +1101,7 @@ int snd_pcm_hw_rule_add(struct snd_pcm_runtime *runtime, unsigned int cond,
        constrs->rules_num++;
        va_end(args);
        return 0;
-}                                  
+}
 
 EXPORT_SYMBOL(snd_pcm_hw_rule_add);
 
index 46c0d03dbecced68ca318dbbe20df52d1da4ab0b..fcb14a09982262d473842aeb55f365b031ebeb70 100644 (file)
@@ -87,7 +87,7 @@ int *load_mixer_volumes(char *name, int *levels, int present)
        int             i, n;
 
        for (i = 0; i < num_mixer_volumes; i++) {
-               if (strcmp(name, mixer_vols[i].name) == 0) {
+               if (strncmp(name, mixer_vols[i].name, 32) == 0) {
                        if (present)
                                mixer_vols[i].num = i;
                        return mixer_vols[i].levels;
@@ -99,7 +99,7 @@ int *load_mixer_volumes(char *name, int *levels, int present)
        }
        n = num_mixer_volumes++;
 
-       strcpy(mixer_vols[n].name, name);
+       strncpy(mixer_vols[n].name, name, 32);
 
        if (present)
                mixer_vols[n].num = n;
index 644e3f14f8ca5aea7af2e465450caab86d2f90cb..98b6d02a36c9c0600a7b26dffbbf1f4f378fccd8 100644 (file)
@@ -1919,6 +1919,16 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
 }
 EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
 
+static int find_empty_mixer_ctl_idx(struct hda_codec *codec, const char *name)
+{
+       int idx;
+       for (idx = 0; idx < 16; idx++) { /* 16 ctlrs should be large enough */
+               if (!_snd_hda_find_mixer_ctl(codec, name, idx))
+                       return idx;
+       }
+       return -EBUSY;
+}
+
 /**
  * snd_hda_ctl_add - Add a control element and assign to the codec
  * @codec: HD-audio codec
@@ -2654,8 +2664,6 @@ static struct snd_kcontrol_new dig_mixes[] = {
        { } /* end */
 };
 
-#define SPDIF_MAX_IDX  4       /* 4 instances should be enough to probe */
-
 /**
  * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
  * @codec: the HDA codec
@@ -2673,12 +2681,8 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
        struct snd_kcontrol_new *dig_mix;
        int idx;
 
-       for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
-               if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Playback Switch",
-                                            idx))
-                       break;
-       }
-       if (idx >= SPDIF_MAX_IDX) {
+       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Playback Switch");
+       if (idx < 0) {
                printk(KERN_ERR "hda_codec: too many IEC958 outputs\n");
                return -EBUSY;
        }
@@ -2829,12 +2833,8 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
        struct snd_kcontrol_new *dig_mix;
        int idx;
 
-       for (idx = 0; idx < SPDIF_MAX_IDX; idx++) {
-               if (!_snd_hda_find_mixer_ctl(codec, "IEC958 Capture Switch",
-                                            idx))
-                       break;
-       }
-       if (idx >= SPDIF_MAX_IDX) {
+       idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch");
+       if (idx < 0) {
                printk(KERN_ERR "hda_codec: too many IEC958 inputs\n");
                return -EBUSY;
        }
@@ -3808,21 +3808,32 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
 
        for (; knew->name; knew++) {
                struct snd_kcontrol *kctl;
+               int addr = 0, idx = 0;
                if (knew->iface == -1)  /* skip this codec private value */
                        continue;
-               kctl = snd_ctl_new1(knew, codec);
-               if (!kctl)
-                       return -ENOMEM;
-               err = snd_hda_ctl_add(codec, 0, kctl);
-               if (err < 0) {
-                       if (!codec->addr)
-                               return err;
+               for (;;) {
                        kctl = snd_ctl_new1(knew, codec);
                        if (!kctl)
                                return -ENOMEM;
-                       kctl->id.device = codec->addr;
+                       if (addr > 0)
+                               kctl->id.device = addr;
+                       if (idx > 0)
+                               kctl->id.index = idx;
                        err = snd_hda_ctl_add(codec, 0, kctl);
-                       if (err < 0)
+                       if (!err)
+                               break;
+                       /* try first with another device index corresponding to
+                        * the codec addr; if it still fails (or it's the
+                        * primary codec), then try another control index
+                        */
+                       if (!addr && codec->addr)
+                               addr = codec->addr;
+                       else if (!idx && !knew->index) {
+                               idx = find_empty_mixer_ctl_idx(codec,
+                                                              knew->name);
+                               if (idx <= 0)
+                                       return err;
+                       } else
                                return err;
                }
        }
index b030c8eba21fdc618fe0b5bfb32cf5b156c39bba..a1c4008af89185449567331db04014a31b87007c 100644 (file)
@@ -2300,6 +2300,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01f6, "Dell Latitude 131L", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1028, 0x0470, "Dell Inspiron 1120", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
index 2d7d7de8498a7947bb9c6180bc757017535c343c..552a09e9211ff355c185314339d48b99d5a0cb65 100644 (file)
@@ -10830,7 +10830,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
        struct auto_pin_cfg *cfg = &spec->autocfg;
-       int i, err;
+       int i, err, type;
+       int type_idx = 0;
        hda_nid_t nid;
 
        for (i = 0; i < cfg->num_inputs; i++) {
@@ -10839,9 +10840,15 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
                nid = cfg->inputs[i].pin;
                if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) {
                        char label[32];
+                       type = cfg->inputs[i].type;
+                       if (i > 0 && type == cfg->inputs[i - 1].type)
+                               type_idx++;
+                       else
+                               type_idx = 0;
                        snprintf(label, sizeof(label), "%s Boost",
                                 hda_get_autocfg_input_label(codec, cfg, i));
-                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0,
+                       err = add_control(spec, ALC_CTL_WIDGET_VOL, label,
+                                         type_idx,
                                  HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT));
                        if (err < 0)
                                return err;
@@ -14799,7 +14806,10 @@ static int alc269_resume(struct hda_codec *codec)
 
 enum {
        ALC269_FIXUP_SONY_VAIO,
+       ALC275_FIX_SONY_VAIO_GPIO2,
        ALC269_FIXUP_DELL_M101Z,
+       ALC269_FIXUP_SKU_IGNORE,
+       ALC269_FIXUP_ASUS_G73JW,
 };
 
 static const struct alc_fixup alc269_fixups[] = {
@@ -14809,6 +14819,14 @@ static const struct alc_fixup alc269_fixups[] = {
                        {}
                }
        },
+       [ALC275_FIX_SONY_VAIO_GPIO2] = {
+               .verbs = (const struct hda_verb[]) {
+                       {0x01, AC_VERB_SET_GPIO_MASK, 0x04},
+                       {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04},
+                       {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
+                       { }
+               }
+       },
        [ALC269_FIXUP_DELL_M101Z] = {
                .verbs = (const struct hda_verb[]) {
                        /* Enables internal speaker */
@@ -14817,11 +14835,26 @@ static const struct alc_fixup alc269_fixups[] = {
                        {}
                }
        },
+       [ALC269_FIXUP_SKU_IGNORE] = {
+               .sku = ALC_FIXUP_SKU_IGNORE,
+       },
+       [ALC269_FIXUP_ASUS_G73JW] = {
+               .pins = (const struct alc_pincfg[]) {
+                       { 0x17, 0x99130111 }, /* subwoofer */
+                       { }
+               }
+       },
 };
 
 static struct snd_pci_quirk alc269_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2),
+       SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2),
+       SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIX_SONY_VAIO_GPIO2),
        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(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
+       SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        {}
 };
 
@@ -15071,28 +15104,29 @@ static int patch_alc269(struct hda_codec *codec)
 
        alc_auto_parse_customize_define(codec);
 
-       coef = alc_read_coef_idx(codec, 0);
-       if ((coef & 0x00f0) == 0x0010) {
-               if (codec->bus->pci->subsystem_vendor == 0x1025 &&
-                   spec->cdefine.platform_type == 1) {
-                       alc_codec_rename(codec, "ALC271X");
-                       spec->codec_variant = ALC269_TYPE_ALC271X;
-               } else if ((coef & 0xf000) == 0x1000) {
-                       spec->codec_variant = ALC269_TYPE_ALC270;
-               } else if ((coef & 0xf000) == 0x2000) {
-                       alc_codec_rename(codec, "ALC259");
-                       spec->codec_variant = ALC269_TYPE_ALC259;
-               } else if ((coef & 0xf000) == 0x3000) {
-                       alc_codec_rename(codec, "ALC258");
-                       spec->codec_variant = ALC269_TYPE_ALC258;
-               } else {
-                       alc_codec_rename(codec, "ALC269VB");
-                       spec->codec_variant = ALC269_TYPE_ALC269VB;
-               }
-       } else
-               alc_fix_pll_init(codec, 0x20, 0x04, 15);
-
-       alc269_fill_coef(codec);
+       if (codec->vendor_id == 0x10ec0269) {
+               coef = alc_read_coef_idx(codec, 0);
+               if ((coef & 0x00f0) == 0x0010) {
+                       if (codec->bus->pci->subsystem_vendor == 0x1025 &&
+                           spec->cdefine.platform_type == 1) {
+                               alc_codec_rename(codec, "ALC271X");
+                               spec->codec_variant = ALC269_TYPE_ALC271X;
+                       } else if ((coef & 0xf000) == 0x1000) {
+                               spec->codec_variant = ALC269_TYPE_ALC270;
+                       } else if ((coef & 0xf000) == 0x2000) {
+                               alc_codec_rename(codec, "ALC259");
+                               spec->codec_variant = ALC269_TYPE_ALC259;
+                       } else if ((coef & 0xf000) == 0x3000) {
+                               alc_codec_rename(codec, "ALC258");
+                               spec->codec_variant = ALC269_TYPE_ALC258;
+                       } else {
+                               alc_codec_rename(codec, "ALC269VB");
+                               spec->codec_variant = ALC269_TYPE_ALC269VB;
+                       }
+               } else
+                       alc_fix_pll_init(codec, 0x20, 0x04, 15);
+               alc269_fill_coef(codec);
+       }
 
        board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST,
                                                  alc269_models,
index efa4225f5fd6c95f9f0218d38002d1ca12d88bd3..f03b2ff90496f86151b01cec6131e9cc94996a42 100644 (file)
@@ -3481,6 +3481,8 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
 
                label = hda_get_input_pin_label(codec, nid, 1);
                snd_hda_add_imux_item(dimux, label, index, &type_idx);
+               if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1)
+                       snd_hda_add_imux_item(imux, label, index, &type_idx);
 
                err = create_elem_capture_vol(codec, nid, label, type_idx,
                                              HDA_INPUT);
@@ -3492,9 +3494,6 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
                        if (err < 0)
                                return err;
                }
-
-               if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1)
-                       snd_hda_add_imux_item(imux, label, index, NULL);
        }
 
        return 0;
index d63e28773eb1841ac7bdd06af0d37a0d5c03013b..6447dbb2f1238f1288c6ed6a797757a08ddd69fa 100644 (file)
@@ -40,7 +40,6 @@ struct max98088_cdata {
 };
 
 struct max98088_priv {
-       u8 reg_cache[M98088_REG_CNT];
        enum max98088_type devtype;
        void *control_data;
        struct max98088_pdata *pdata;
@@ -1588,7 +1587,7 @@ static int max98088_dai2_set_fmt(struct snd_soc_dai *codec_dai,
 
 static void max98088_sync_cache(struct snd_soc_codec *codec)
 {
-       struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int i;
 
        if (!codec->cache_sync)
@@ -1599,14 +1598,14 @@ static void max98088_sync_cache(struct snd_soc_codec *codec)
        /* write back cached values if they're writeable and
         * different from the hardware default.
         */
-       for (i = 1; i < ARRAY_SIZE(max98088->reg_cache); i++) {
+       for (i = 1; i < codec->driver->reg_cache_size; i++) {
                if (!max98088_access[i].writable)
                        continue;
 
-               if (max98088->reg_cache[i] == max98088_reg[i])
+               if (reg_cache[i] == max98088_reg[i])
                        continue;
 
-               snd_soc_write(codec, i, max98088->reg_cache[i]);
+               snd_soc_write(codec, i, reg_cache[i]);
        }
 
        codec->cache_sync = 0;
@@ -1951,7 +1950,6 @@ static int max98088_probe(struct snd_soc_codec *codec)
        int ret = 0;
 
        codec->cache_sync = 1;
-       memcpy(codec->reg_cache, max98088_reg, sizeof(max98088_reg));
 
        ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
        if (ret != 0) {
index 9a433a5396cb781727e39a4c1c6005f1bbc9a421..deca79ea2b4b98ab6d3232c9cb3c1b4c3e6858dd 100644 (file)
@@ -41,7 +41,6 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = {
 /* codec private data */
 struct wm8523_priv {
        enum snd_soc_control_type control_type;
-       u16 reg_cache[WM8523_REGISTER_COUNT];
        struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES];
        unsigned int sysclk;
        unsigned int rate_constraint_list[WM8523_NUM_RATES];
@@ -314,6 +313,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
        struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int ret, i;
 
        switch (level) {
@@ -344,7 +344,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
                        /* Sync back default/cached values */
                        for (i = WM8523_AIF_CTRL1;
                             i < WM8523_MAX_REGISTER; i++)
-                               snd_soc_write(codec, i, wm8523->reg_cache[i]);
+                               snd_soc_write(codec, i, reg_cache[i]);
 
 
                        msleep(100);
@@ -414,6 +414,7 @@ static int wm8523_resume(struct snd_soc_codec *codec)
 static int wm8523_probe(struct snd_soc_codec *codec)
 {
        struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int ret, i;
 
        codec->hw_write = (hw_write_t)i2c_master_send;
@@ -470,8 +471,8 @@ static int wm8523_probe(struct snd_soc_codec *codec)
        }
 
        /* Change some default settings - latch VU and enable ZC */
-       wm8523->reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
-       wm8523->reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
+       reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU;
+       reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC;
 
        wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
index 879dff2714dd3c522211dbac3c636a5191d8ce4b..8725d4e754310d86774935b48e1a2443fe04405c 100644 (file)
 static const u16 wm8580_reg[] = {
        0x0121, 0x017e, 0x007d, 0x0014, /*R3*/
        0x0121, 0x017e, 0x007d, 0x0194, /*R7*/
-       0x001c, 0x0002, 0x0002, 0x00c2, /*R11*/
+       0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/
        0x0182, 0x0082, 0x000a, 0x0024, /*R15*/
        0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/
        0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/
index 90e31e9aa6f7c66346c8360a3c1ab900519e4a98..aea60ef8aba73da14e7cd17f62b72955adfd645a 100644 (file)
@@ -41,7 +41,6 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = {
 /* codec private data */
 struct wm8741_priv {
        enum snd_soc_control_type control_type;
-       u16 reg_cache[WM8741_REGISTER_COUNT];
        struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES];
        unsigned int sysclk;
        struct snd_pcm_hw_constraint_list *sysclk_constraints;
@@ -422,6 +421,7 @@ static int wm8741_resume(struct snd_soc_codec *codec)
 static int wm8741_probe(struct snd_soc_codec *codec)
 {
        struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int ret = 0;
 
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
@@ -437,10 +437,10 @@ static int wm8741_probe(struct snd_soc_codec *codec)
        }
 
        /* Change some default settings - latch VU */
-       wm8741->reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
-       wm8741->reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
-       wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
-       wm8741->reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
+       reg_cache[WM8741_DACLLSB_ATTENUATION] |= WM8741_UPDATELL;
+       reg_cache[WM8741_DACLMSB_ATTENUATION] |= WM8741_UPDATELM;
+       reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERL;
+       reg_cache[WM8741_DACRLSB_ATTENUATION] |= WM8741_UPDATERM;
 
        snd_soc_add_controls(codec, wm8741_snd_controls,
                             ARRAY_SIZE(wm8741_snd_controls));
index 8f679a13f2bcaae23653adaffafff6fedcd8e66f..87caae59e939c78465750f470d5d4ce35ee505d3 100644 (file)
@@ -65,22 +65,22 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
  * are using 2 wire for device control, so we cache them instead.
  */
 static const u16 wm8753_reg[] = {
-       0x0008, 0x0000, 0x000a, 0x000a,
-       0x0033, 0x0000, 0x0007, 0x00ff,
-       0x00ff, 0x000f, 0x000f, 0x007b,
-       0x0000, 0x0032, 0x0000, 0x00c3,
-       0x00c3, 0x00c0, 0x0000, 0x0000,
+       0x0000, 0x0008, 0x0000, 0x000a,
+       0x000a, 0x0033, 0x0000, 0x0007,
+       0x00ff, 0x00ff, 0x000f, 0x000f,
+       0x007b, 0x0000, 0x0032, 0x0000,
+       0x00c3, 0x00c3, 0x00c0, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000,
-       0x0000, 0x0000, 0x0000, 0x0055,
-       0x0005, 0x0050, 0x0055, 0x0050,
-       0x0055, 0x0050, 0x0055, 0x0079,
-       0x0079, 0x0079, 0x0079, 0x0079,
        0x0000, 0x0000, 0x0000, 0x0000,
-       0x0097, 0x0097, 0x0000, 0x0004,
-       0x0000, 0x0083, 0x0024, 0x01ba,
-       0x0000, 0x0083, 0x0024, 0x01ba,
-       0x0000, 0x0000, 0x0000
+       0x0055, 0x0005, 0x0050, 0x0055,
+       0x0050, 0x0055, 0x0050, 0x0055,
+       0x0079, 0x0079, 0x0079, 0x0079,
+       0x0079, 0x0000, 0x0000, 0x0000,
+       0x0000, 0x0097, 0x0097, 0x0000,
+       0x0004, 0x0000, 0x0083, 0x0024,
+       0x01ba, 0x0000, 0x0083, 0x0024,
+       0x01ba, 0x0000, 0x0000, 0x0000
 };
 
 /* codec private data */
@@ -88,57 +88,10 @@ struct wm8753_priv {
        enum snd_soc_control_type control_type;
        unsigned int sysclk;
        unsigned int pcmclk;
-       u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
        int dai_func;
 };
 
-/*
- * read wm8753 register cache
- */
-static inline unsigned int wm8753_read_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
-               return -1;
-       return cache[reg - 1];
-}
-
-/*
- * write wm8753 register cache
- */
-static inline void wm8753_write_reg_cache(struct snd_soc_codec *codec,
-       unsigned int reg, unsigned int value)
-{
-       u16 *cache = codec->reg_cache;
-       if (reg < 1 || reg >= (ARRAY_SIZE(wm8753_reg) + 1))
-               return;
-       cache[reg - 1] = value;
-}
-
-/*
- * write to the WM8753 register space
- */
-static int wm8753_write(struct snd_soc_codec *codec, unsigned int reg,
-       unsigned int value)
-{
-       u8 data[2];
-
-       /* data is
-        *   D15..D9 WM8753 register offset
-        *   D8...D0 register data
-        */
-       data[0] = (reg << 1) | ((value >> 8) & 0x0001);
-       data[1] = value & 0x00ff;
-
-       wm8753_write_reg_cache(codec, reg, value);
-       if (codec->hw_write(codec->control_data, data, 2) == 2)
-               return 0;
-       else
-               return -EIO;
-}
-
-#define wm8753_reset(c) wm8753_write(c, WM8753_RESET, 0)
+#define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0)
 
 /*
  * WM8753 Controls
@@ -218,7 +171,7 @@ static int wm8753_get_dai(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-       int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+       int mode = snd_soc_read(codec, WM8753_IOCTL);
 
        ucontrol->value.integer.value[0] = (mode & 0xc) >> 2;
        return 0;
@@ -228,7 +181,7 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
        struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec =  snd_kcontrol_chip(kcontrol);
-       int mode = wm8753_read_reg_cache(codec, WM8753_IOCTL);
+       int mode = snd_soc_read(codec, WM8753_IOCTL);
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
        if (((mode & 0xc) >> 2) == ucontrol->value.integer.value[0])
@@ -738,17 +691,17 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
        if (pll_id == WM8753_PLL1) {
                offset = 0;
                enable = 0x10;
-               reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xffef;
+               reg = snd_soc_read(codec, WM8753_CLOCK) & 0xffef;
        } else {
                offset = 4;
                enable = 0x8;
-               reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfff7;
+               reg = snd_soc_read(codec, WM8753_CLOCK) & 0xfff7;
        }
 
        if (!freq_in || !freq_out) {
                /* disable PLL  */
-               wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
-               wm8753_write(codec, WM8753_CLOCK, reg);
+               snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0026);
+               snd_soc_write(codec, WM8753_CLOCK, reg);
                return 0;
        } else {
                u16 value = 0;
@@ -759,20 +712,20 @@ static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
                /* set up N and K PLL divisor ratios */
                /* bits 8:5 = PLL_N, bits 3:0 = PLL_K[21:18] */
                value = (pll_div.n << 5) + ((pll_div.k & 0x3c0000) >> 18);
-               wm8753_write(codec, WM8753_PLL1CTL2 + offset, value);
+               snd_soc_write(codec, WM8753_PLL1CTL2 + offset, value);
 
                /* bits 8:0 = PLL_K[17:9] */
                value = (pll_div.k & 0x03fe00) >> 9;
-               wm8753_write(codec, WM8753_PLL1CTL3 + offset, value);
+               snd_soc_write(codec, WM8753_PLL1CTL3 + offset, value);
 
                /* bits 8:0 = PLL_K[8:0] */
                value = pll_div.k & 0x0001ff;
-               wm8753_write(codec, WM8753_PLL1CTL4 + offset, value);
+               snd_soc_write(codec, WM8753_PLL1CTL4 + offset, value);
 
                /* set PLL as input and enable */
-               wm8753_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
+               snd_soc_write(codec, WM8753_PLL1CTL1 + offset, 0x0027 |
                        (pll_div.div2 << 3));
-               wm8753_write(codec, WM8753_CLOCK, reg | enable);
+               snd_soc_write(codec, WM8753_CLOCK, reg | enable);
        }
        return 0;
 }
@@ -879,7 +832,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01ec;
+       u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01ec;
 
        /* interface format */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -901,7 +854,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8753_write(codec, WM8753_PCM, voice);
+       snd_soc_write(codec, WM8753_PCM, voice);
        return 0;
 }
 
@@ -922,8 +875,8 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
-       u16 voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x01f3;
-       u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x017f;
+       u16 voice = snd_soc_read(codec, WM8753_PCM) & 0x01f3;
+       u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x017f;
 
        /* bit size */
        switch (params_format(params)) {
@@ -943,9 +896,9 @@ static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
        /* sample rate */
        if (params_rate(params) * 384 == wm8753->pcmclk)
                srate |= 0x80;
-       wm8753_write(codec, WM8753_SRATE1, srate);
+       snd_soc_write(codec, WM8753_SRATE1, srate);
 
-       wm8753_write(codec, WM8753_PCM, voice);
+       snd_soc_write(codec, WM8753_PCM, voice);
        return 0;
 }
 
@@ -958,8 +911,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 voice, ioctl;
 
-       voice = wm8753_read_reg_cache(codec, WM8753_PCM) & 0x011f;
-       ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x015d;
+       voice = snd_soc_read(codec, WM8753_PCM) & 0x011f;
+       ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x015d;
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1013,8 +966,8 @@ static int wm8753_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8753_write(codec, WM8753_PCM, voice);
-       wm8753_write(codec, WM8753_IOCTL, ioctl);
+       snd_soc_write(codec, WM8753_PCM, voice);
+       snd_soc_write(codec, WM8753_IOCTL, ioctl);
        return 0;
 }
 
@@ -1026,16 +979,16 @@ static int wm8753_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
 
        switch (div_id) {
        case WM8753_PCMDIV:
-               reg = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0x003f;
-               wm8753_write(codec, WM8753_CLOCK, reg | div);
+               reg = snd_soc_read(codec, WM8753_CLOCK) & 0x003f;
+               snd_soc_write(codec, WM8753_CLOCK, reg | div);
                break;
        case WM8753_BCLKDIV:
-               reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x01c7;
-               wm8753_write(codec, WM8753_SRATE2, reg | div);
+               reg = snd_soc_read(codec, WM8753_SRATE2) & 0x01c7;
+               snd_soc_write(codec, WM8753_SRATE2, reg | div);
                break;
        case WM8753_VXCLKDIV:
-               reg = wm8753_read_reg_cache(codec, WM8753_SRATE2) & 0x003f;
-               wm8753_write(codec, WM8753_SRATE2, reg | div);
+               reg = snd_soc_read(codec, WM8753_SRATE2) & 0x003f;
+               snd_soc_write(codec, WM8753_SRATE2, reg | div);
                break;
        default:
                return -EINVAL;
@@ -1050,7 +1003,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
                unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
-       u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01e0;
+       u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01e0;
 
        /* interface format */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -1072,7 +1025,7 @@ static int wm8753_hdac_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8753_write(codec, WM8753_HIFI, hifi);
+       snd_soc_write(codec, WM8753_HIFI, hifi);
        return 0;
 }
 
@@ -1085,8 +1038,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
        struct snd_soc_codec *codec = codec_dai->codec;
        u16 ioctl, hifi;
 
-       hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x011f;
-       ioctl = wm8753_read_reg_cache(codec, WM8753_IOCTL) & 0x00ae;
+       hifi = snd_soc_read(codec, WM8753_HIFI) & 0x011f;
+       ioctl = snd_soc_read(codec, WM8753_IOCTL) & 0x00ae;
 
        /* set master/slave audio interface */
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -1140,8 +1093,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
                return -EINVAL;
        }
 
-       wm8753_write(codec, WM8753_HIFI, hifi);
-       wm8753_write(codec, WM8753_IOCTL, ioctl);
+       snd_soc_write(codec, WM8753_HIFI, hifi);
+       snd_soc_write(codec, WM8753_IOCTL, ioctl);
        return 0;
 }
 
@@ -1162,8 +1115,8 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct snd_soc_codec *codec = rtd->codec;
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
-       u16 srate = wm8753_read_reg_cache(codec, WM8753_SRATE1) & 0x01c0;
-       u16 hifi = wm8753_read_reg_cache(codec, WM8753_HIFI) & 0x01f3;
+       u16 srate = snd_soc_read(codec, WM8753_SRATE1) & 0x01c0;
+       u16 hifi = snd_soc_read(codec, WM8753_HIFI) & 0x01f3;
        int coeff;
 
        /* is digital filter coefficient valid ? */
@@ -1172,7 +1125,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
                printk(KERN_ERR "wm8753 invalid MCLK or rate\n");
                return coeff;
        }
-       wm8753_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
+       snd_soc_write(codec, WM8753_SRATE1, srate | (coeff_div[coeff].sr << 1) |
                coeff_div[coeff].usb);
 
        /* bit size */
@@ -1190,7 +1143,7 @@ static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
                break;
        }
 
-       wm8753_write(codec, WM8753_HIFI, hifi);
+       snd_soc_write(codec, WM8753_HIFI, hifi);
        return 0;
 }
 
@@ -1201,8 +1154,8 @@ static int wm8753_mode1v_set_dai_fmt(struct snd_soc_dai *codec_dai,
        u16 clock;
 
        /* set clk source as pcmclk */
-       clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
-       wm8753_write(codec, WM8753_CLOCK, clock);
+       clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+       snd_soc_write(codec, WM8753_CLOCK, clock);
 
        if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
                return -EINVAL;
@@ -1224,8 +1177,8 @@ static int wm8753_mode2_set_dai_fmt(struct snd_soc_dai *codec_dai,
        u16 clock;
 
        /* set clk source as pcmclk */
-       clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
-       wm8753_write(codec, WM8753_CLOCK, clock);
+       clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+       snd_soc_write(codec, WM8753_CLOCK, clock);
 
        if (wm8753_vdac_adc_set_dai_fmt(codec_dai, fmt) < 0)
                return -EINVAL;
@@ -1239,8 +1192,8 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
        u16 clock;
 
        /* set clk source as mclk */
-       clock = wm8753_read_reg_cache(codec, WM8753_CLOCK) & 0xfffb;
-       wm8753_write(codec, WM8753_CLOCK, clock | 0x4);
+       clock = snd_soc_read(codec, WM8753_CLOCK) & 0xfffb;
+       snd_soc_write(codec, WM8753_CLOCK, clock | 0x4);
 
        if (wm8753_hdac_set_dai_fmt(codec_dai, fmt) < 0)
                return -EINVAL;
@@ -1252,19 +1205,19 @@ static int wm8753_mode3_4_set_dai_fmt(struct snd_soc_dai *codec_dai,
 static int wm8753_mute(struct snd_soc_dai *dai, int mute)
 {
        struct snd_soc_codec *codec = dai->codec;
-       u16 mute_reg = wm8753_read_reg_cache(codec, WM8753_DAC) & 0xfff7;
+       u16 mute_reg = snd_soc_read(codec, WM8753_DAC) & 0xfff7;
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
 
        /* the digital mute covers the HiFi and Voice DAC's on the WM8753.
         * make sure we check if they are not both active when we mute */
        if (mute && wm8753->dai_func == 1) {
                if (!codec->active)
-                       wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
+                       snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
        } else {
                if (mute)
-                       wm8753_write(codec, WM8753_DAC, mute_reg | 0x8);
+                       snd_soc_write(codec, WM8753_DAC, mute_reg | 0x8);
                else
-                       wm8753_write(codec, WM8753_DAC, mute_reg);
+                       snd_soc_write(codec, WM8753_DAC, mute_reg);
        }
 
        return 0;
@@ -1273,23 +1226,23 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute)
 static int wm8753_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
-       u16 pwr_reg = wm8753_read_reg_cache(codec, WM8753_PWR1) & 0xfe3e;
+       u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
                /* set vmid to 50k and unmute dac */
-               wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
+               snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0);
                break;
        case SND_SOC_BIAS_PREPARE:
                /* set vmid to 5k for quick power up */
-               wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
+               snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1);
                break;
        case SND_SOC_BIAS_STANDBY:
                /* mute dac and set vmid to 500k, enable VREF */
-               wm8753_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
+               snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141);
                break;
        case SND_SOC_BIAS_OFF:
-               wm8753_write(codec, WM8753_PWR1, 0x0001);
+               snd_soc_write(codec, WM8753_PWR1, 0x0001);
                break;
        }
        codec->bias_level = level;
@@ -1477,7 +1430,7 @@ static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
                else
                        dai->driver = &wm8753_all_dai[(wm8753->dai_func << 1) + 1];
        }
-       wm8753_write(codec, WM8753_IOCTL, wm8753->dai_func);
+       snd_soc_write(codec, WM8753_IOCTL, wm8753->dai_func);
 }
 
 static void wm8753_work(struct work_struct *work)
@@ -1495,22 +1448,19 @@ static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
 
 static int wm8753_resume(struct snd_soc_codec *codec)
 {
+       u16 *reg_cache = codec->reg_cache;
        int i;
-       u8 data[2];
-       u16 *cache = codec->reg_cache;
 
        /* Sync reg_cache with the hardware */
-       for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) {
-               if (i + 1 == WM8753_RESET)
+       for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
+               if (i == WM8753_RESET)
                        continue;
 
                /* No point in writing hardware default values back */
-               if (cache[i] == wm8753_reg[i])
+               if (reg_cache[i] == wm8753_reg[i])
                        continue;
 
-               data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
-               data[1] = cache[i] & 0x00ff;
-               codec->hw_write(codec->control_data, data, 2);
+               snd_soc_write(codec, i, reg_cache[i]);
        }
 
        wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1548,7 +1498,7 @@ static int run_delayed_work(struct delayed_work *dwork)
 static int wm8753_probe(struct snd_soc_codec *codec)
 {
        struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0, reg;
+       int ret;
 
        INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
 
@@ -1573,26 +1523,16 @@ static int wm8753_probe(struct snd_soc_codec *codec)
                              msecs_to_jiffies(caps_charge));
 
        /* set the update bits */
-       reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
-       wm8753_write(codec, WM8753_LDAC, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_RDAC);
-       wm8753_write(codec, WM8753_RDAC, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_LADC);
-       wm8753_write(codec, WM8753_LADC, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_RADC);
-       wm8753_write(codec, WM8753_RADC, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_LOUT1V);
-       wm8753_write(codec, WM8753_LOUT1V, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_ROUT1V);
-       wm8753_write(codec, WM8753_ROUT1V, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_LOUT2V);
-       wm8753_write(codec, WM8753_LOUT2V, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_ROUT2V);
-       wm8753_write(codec, WM8753_ROUT2V, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_LINVOL);
-       wm8753_write(codec, WM8753_LINVOL, reg | 0x0100);
-       reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
-       wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
+       snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_ROUT2V, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100);
+       snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
 
        snd_soc_add_controls(codec, wm8753_snd_controls,
                             ARRAY_SIZE(wm8753_snd_controls));
index fca60a0b57b83a807a946b86576093237b090f1f..1ec12eff06205f9023b57c5da7b836d6e81a1f4b 100644 (file)
@@ -50,8 +50,6 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
 /* codec private data */
 struct wm8904_priv {
 
-       u16 reg_cache[WM8904_MAX_REGISTER + 1];
-
        enum wm8904_type devtype;
        void *control_data;
 
@@ -818,7 +816,8 @@ static int wm8904_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8904->deemph;
+       ucontrol->value.enumerated.item[0] = wm8904->deemph;
+       return 0;
 }
 
 static int wm8904_put_deemph(struct snd_kcontrol *kcontrol,
@@ -2093,7 +2092,7 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
 
 static void wm8904_sync_cache(struct snd_soc_codec *codec)
 {
-       struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int i;
 
        if (!codec->cache_sync)
@@ -2104,14 +2103,14 @@ static void wm8904_sync_cache(struct snd_soc_codec *codec)
        /* Sync back cached values if they're different from the
         * hardware default.
         */
-       for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) {
+       for (i = 1; i < codec->driver->reg_cache_size; i++) {
                if (!wm8904_access[i].writable)
                        continue;
 
-               if (wm8904->reg_cache[i] == wm8904_reg[i])
+               if (reg_cache[i] == wm8904_reg[i])
                        continue;
 
-               snd_soc_write(codec, i, wm8904->reg_cache[i]);
+               snd_soc_write(codec, i, reg_cache[i]);
        }
 
        codec->cache_sync = 0;
@@ -2370,6 +2369,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
 {
        struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec);
        struct wm8904_pdata *pdata = wm8904->pdata;
+       u16 *reg_cache = codec->reg_cache;
        int ret, i;
 
        codec->cache_sync = 1;
@@ -2436,19 +2436,19 @@ static int wm8904_probe(struct snd_soc_codec *codec)
        }
 
        /* Change some default settings - latch VU and enable ZC */
-       wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
-       wm8904->reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
-       wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
-       wm8904->reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
-       wm8904->reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
+       reg_cache[WM8904_ADC_DIGITAL_VOLUME_LEFT] |= WM8904_ADC_VU;
+       reg_cache[WM8904_ADC_DIGITAL_VOLUME_RIGHT] |= WM8904_ADC_VU;
+       reg_cache[WM8904_DAC_DIGITAL_VOLUME_LEFT] |= WM8904_DAC_VU;
+       reg_cache[WM8904_DAC_DIGITAL_VOLUME_RIGHT] |= WM8904_DAC_VU;
+       reg_cache[WM8904_ANALOGUE_OUT1_LEFT] |= WM8904_HPOUT_VU |
                WM8904_HPOUTLZC;
-       wm8904->reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
+       reg_cache[WM8904_ANALOGUE_OUT1_RIGHT] |= WM8904_HPOUT_VU |
                WM8904_HPOUTRZC;
-       wm8904->reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
+       reg_cache[WM8904_ANALOGUE_OUT2_LEFT] |= WM8904_LINEOUT_VU |
                WM8904_LINEOUTLZC;
-       wm8904->reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
+       reg_cache[WM8904_ANALOGUE_OUT2_RIGHT] |= WM8904_LINEOUT_VU |
                WM8904_LINEOUTRZC;
-       wm8904->reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
+       reg_cache[WM8904_CLOCK_RATES_0] &= ~WM8904_SR_MODE;
 
        /* Apply configuration from the platform data. */
        if (wm8904->pdata) {
@@ -2456,23 +2456,23 @@ static int wm8904_probe(struct snd_soc_codec *codec)
                        if (!pdata->gpio_cfg[i])
                                continue;
 
-                       wm8904->reg_cache[WM8904_GPIO_CONTROL_1 + i]
+                       reg_cache[WM8904_GPIO_CONTROL_1 + i]
                                = pdata->gpio_cfg[i] & 0xffff;
                }
 
                /* Zero is the default value for these anyway */
                for (i = 0; i < WM8904_MIC_REGS; i++)
-                       wm8904->reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
+                       reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i]
                                = pdata->mic_cfg[i];
        }
 
        /* Set Class W by default - this will be managed by the Class
         * G widget at runtime where bypass paths are available.
         */
-       wm8904->reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
+       reg_cache[WM8904_CLASS_W_0] |= WM8904_CP_DYN_PWR;
 
        /* Use normal bias source */
-       wm8904->reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
+       reg_cache[WM8904_BIAS_CONTROL_0] &= ~WM8904_POBCTRL;
 
        wm8904_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
index 2cb16f895c4607c9d323ea3cbb9d8e31c4741cb1..23086e2c976abf686c62624da2fd00ff59417594 100644 (file)
@@ -768,6 +768,7 @@ static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
 
        i2c_set_clientdata(i2c, wm8940);
        wm8940->control_data = i2c;
+       wm8940->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8940, &wm8940_dai, 1);
index f89ad6c9a80b9162e7040ea6fe76b434c9f743f1..2ac35b0be86acb37faaabdb1c0f81b321a2bb741 100644 (file)
@@ -42,8 +42,6 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
 struct wm8955_priv {
        enum snd_soc_control_type control_type;
 
-       u16 reg_cache[WM8955_MAX_REGISTER + 1];
-
        unsigned int mclk_rate;
 
        int deemph;
@@ -380,7 +378,8 @@ static int wm8955_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8955->deemph;
+       ucontrol->value.enumerated.item[0] = wm8955->deemph;
+       return 0;
 }
 
 static int wm8955_put_deemph(struct snd_kcontrol *kcontrol,
@@ -767,6 +766,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int ret, i;
 
        switch (level) {
@@ -799,14 +799,14 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
                        /* Sync back cached values if they're
                         * different from the hardware default.
                         */
-                       for (i = 0; i < ARRAY_SIZE(wm8955->reg_cache); i++) {
+                       for (i = 0; i < codec->driver->reg_cache_size; i++) {
                                if (i == WM8955_RESET)
                                        continue;
 
-                               if (wm8955->reg_cache[i] == wm8955_reg[i])
+                               if (reg_cache[i] == wm8955_reg[i])
                                        continue;
 
-                               snd_soc_write(codec, i, wm8955->reg_cache[i]);
+                               snd_soc_write(codec, i, reg_cache[i]);
                        }
 
                        /* Enable VREF and VMID */
@@ -901,6 +901,7 @@ static int wm8955_probe(struct snd_soc_codec *codec)
 {
        struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
        struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
+       u16 *reg_cache = codec->reg_cache;
        int ret, i;
 
        ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
@@ -933,25 +934,25 @@ static int wm8955_probe(struct snd_soc_codec *codec)
        }
 
        /* Change some default settings - latch VU and enable ZC */
-       wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
-       wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
-       wm8955->reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
-       wm8955->reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
-       wm8955->reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
-       wm8955->reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
-       wm8955->reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
+       reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
+       reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
+       reg_cache[WM8955_LOUT1_VOLUME] |= WM8955_LO1VU | WM8955_LO1ZC;
+       reg_cache[WM8955_ROUT1_VOLUME] |= WM8955_RO1VU | WM8955_RO1ZC;
+       reg_cache[WM8955_LOUT2_VOLUME] |= WM8955_LO2VU | WM8955_LO2ZC;
+       reg_cache[WM8955_ROUT2_VOLUME] |= WM8955_RO2VU | WM8955_RO2ZC;
+       reg_cache[WM8955_MONOOUT_VOLUME] |= WM8955_MOZC;
 
        /* Also enable adaptive bass boost by default */
-       wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
+       reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
 
        /* Set platform data values */
        if (pdata) {
                if (pdata->out2_speaker)
-                       wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]
+                       reg_cache[WM8955_ADDITIONAL_CONTROL_2]
                                |= WM8955_ROUT2INV;
 
                if (pdata->monoin_diff)
-                       wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]
+                       reg_cache[WM8955_MONO_OUT_MIX_1]
                                |= WM8955_DMEN;
        }
 
@@ -1002,6 +1003,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8955);
+       wm8955->control_type = SND_SOC_I2C;
 
        ret = snd_soc_register_codec(&i2c->dev,
                        &soc_codec_dev_wm8955, &wm8955_dai, 1);
index 8d5efb333c33f260b271af07e9352b14679f0502..ff6ff2f529d2a97f9e2522ceff5df18355cecd5c 100644 (file)
@@ -138,7 +138,8 @@ static int wm8960_get_deemph(struct snd_kcontrol *kcontrol,
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
        struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
 
-       return wm8960->deemph;
+       ucontrol->value.enumerated.item[0] = wm8960->deemph;
+       return 0;
 }
 
 static int wm8960_put_deemph(struct snd_kcontrol *kcontrol,
@@ -1012,6 +1013,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm8960);
+       wm8960->control_type = SND_SOC_I2C;
        wm8960->control_data = i2c;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 1304ca91a11c708c567f69c45052c95f1f7be17e..7c421cc837bd3d697969b6f0c0f94f0ecb7abc5f 100644 (file)
@@ -52,8 +52,6 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
 struct wm8962_priv {
        struct snd_soc_codec *codec;
 
-       u16 reg_cache[WM8962_MAX_REGISTER + 1];
-
        int sysclk;
        int sysclk_rate;
 
@@ -1991,8 +1989,7 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
                            struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-       u16 *reg_cache = wm8962->reg_cache;
+       u16 *reg_cache = codec->reg_cache;
        int ret;
 
        /* Apply the update (if any) */
@@ -2020,8 +2017,7 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
                            struct snd_ctl_elem_value *ucontrol)
 {
        struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-       u16 *reg_cache = wm8962->reg_cache;
+       u16 *reg_cache = codec->reg_cache;
        int ret;
 
        /* Apply the update (if any) */
@@ -2329,8 +2325,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
                         struct snd_kcontrol *kcontrol, int event)
 {
        struct snd_soc_codec *codec = w->codec;
-       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
-       u16 *reg_cache = wm8962->reg_cache;
+       u16 *reg_cache = codec->reg_cache;
        int reg;
 
        switch (w->shift) {
@@ -2719,7 +2714,7 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
 
 static void wm8962_sync_cache(struct snd_soc_codec *codec)
 {
-       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int i;
 
        if (!codec->cache_sync)
@@ -2732,13 +2727,13 @@ static void wm8962_sync_cache(struct snd_soc_codec *codec)
        /* Sync back cached values if they're different from the
         * hardware default.
         */
-       for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+       for (i = 1; i < codec->driver->reg_cache_size; i++) {
                if (i == WM8962_SOFTWARE_RESET)
                        continue;
-               if (wm8962->reg_cache[i] == wm8962_reg[i])
+               if (reg_cache[i] == wm8962_reg[i])
                        continue;
 
-               snd_soc_write(codec, i, wm8962->reg_cache[i]);
+               snd_soc_write(codec, i, reg_cache[i]);
        }
 
        codec->cache_sync = 0;
@@ -3406,12 +3401,11 @@ EXPORT_SYMBOL_GPL(wm8962_mic_detect);
 #ifdef CONFIG_PM
 static int wm8962_resume(struct snd_soc_codec *codec)
 {
-       struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
        u16 *reg_cache = codec->reg_cache;
        int i;
 
        /* Restore the registers */
-       for (i = 1; i < ARRAY_SIZE(wm8962->reg_cache); i++) {
+       for (i = 1; i < codec->driver->reg_cache_size; i++) {
                switch (i) {
                case WM8962_SOFTWARE_RESET:
                        continue;
@@ -3705,6 +3699,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
        struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
        struct i2c_client *i2c = container_of(codec->dev, struct i2c_client,
                                              dev);
+       u16 *reg_cache = codec->reg_cache;
        int i, trigger, irq_pol;
 
        wm8962->codec = codec;
@@ -3804,7 +3799,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
 
                /* Put the speakers into mono mode? */
                if (pdata->spk_mono)
-                       wm8962->reg_cache[WM8962_CLASS_D_CONTROL_2]
+                       reg_cache[WM8962_CLASS_D_CONTROL_2]
                                |= WM8962_SPK_MONO;
 
                /* Micbias setup, detection enable and detection
@@ -3819,16 +3814,16 @@ static int wm8962_probe(struct snd_soc_codec *codec)
        }
 
        /* Latch volume update bits */
-       wm8962->reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
-       wm8962->reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
-       wm8962->reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
-       wm8962->reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;    
-       wm8962->reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
-       wm8962->reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
-       wm8962->reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
-       wm8962->reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
-       wm8962->reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
-       wm8962->reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
+       reg_cache[WM8962_LEFT_INPUT_VOLUME] |= WM8962_IN_VU;
+       reg_cache[WM8962_RIGHT_INPUT_VOLUME] |= WM8962_IN_VU;
+       reg_cache[WM8962_LEFT_ADC_VOLUME] |= WM8962_ADC_VU;
+       reg_cache[WM8962_RIGHT_ADC_VOLUME] |= WM8962_ADC_VU;
+       reg_cache[WM8962_LEFT_DAC_VOLUME] |= WM8962_DAC_VU;
+       reg_cache[WM8962_RIGHT_DAC_VOLUME] |= WM8962_DAC_VU;
+       reg_cache[WM8962_SPKOUTL_VOLUME] |= WM8962_SPKOUT_VU;
+       reg_cache[WM8962_SPKOUTR_VOLUME] |= WM8962_SPKOUT_VU;
+       reg_cache[WM8962_HPOUTL_VOLUME] |= WM8962_HPOUT_VU;
+       reg_cache[WM8962_HPOUTR_VOLUME] |= WM8962_HPOUT_VU;
 
        wm8962_add_widgets(codec);
 
index 63f6dbf5d07021887084e57541591bf1fa570fb3..9f18db6e167c0c86924b08e434d671bea98c8ff1 100644 (file)
@@ -718,6 +718,7 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
        if (wm8971 == NULL)
                return -ENOMEM;
 
+       wm8971->control_type = SND_SOC_I2C;
        i2c_set_clientdata(i2c, wm8971);
 
        ret = snd_soc_register_codec(&i2c->dev,
index ecc7c37180c7ad2158f11b9de1579bde332cb44d..a486670966bd7e6a44470ece6918fab24c638c2b 100644 (file)
@@ -1335,6 +1335,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
                return -ENOMEM;
 
        i2c_set_clientdata(i2c, wm9081);
+       wm9081->control_type = SND_SOC_I2C;
        wm9081->control_data = i2c;
 
        ret = snd_soc_register_codec(&i2c->dev,
index 99c046ba46bb6ed637d356579a2f4af9d1841bc3..6e5f64f627cb82e6c7379ab389ec0a10e45d9b0a 100644 (file)
@@ -141,7 +141,6 @@ static const u16 wm9090_reg_defaults[] = {
 /* This struct is used to save the context */
 struct wm9090_priv {
        struct mutex mutex;
-       u16 reg_cache[WM9090_MAX_REGISTER + 1];
        struct wm9090_platform_data pdata;
        void *control_data;
 };
@@ -552,6 +551,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
 static int wm9090_probe(struct snd_soc_codec *codec)
 {
        struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
+       u16 *reg_cache = codec->reg_cache;
        int ret;
 
        codec->control_data = wm9090->control_data;
@@ -576,22 +576,22 @@ static int wm9090_probe(struct snd_soc_codec *codec)
        /* Configure some defaults; they will be written out when we
         * bring the bias up.
         */
-       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
+       reg_cache[WM9090_IN1_LINE_INPUT_A_VOLUME] |= WM9090_IN1_VU
                | WM9090_IN1A_ZC;
-       wm9090->reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
+       reg_cache[WM9090_IN1_LINE_INPUT_B_VOLUME] |= WM9090_IN1_VU
                | WM9090_IN1B_ZC;
-       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
+       reg_cache[WM9090_IN2_LINE_INPUT_A_VOLUME] |= WM9090_IN2_VU
                | WM9090_IN2A_ZC;
-       wm9090->reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
+       reg_cache[WM9090_IN2_LINE_INPUT_B_VOLUME] |= WM9090_IN2_VU
                | WM9090_IN2B_ZC;
-       wm9090->reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
+       reg_cache[WM9090_SPEAKER_VOLUME_LEFT] |=
                WM9090_SPKOUT_VU | WM9090_SPKOUTL_ZC;
-       wm9090->reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
+       reg_cache[WM9090_LEFT_OUTPUT_VOLUME] |=
                WM9090_HPOUT1_VU | WM9090_HPOUT1L_ZC;
-       wm9090->reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
+       reg_cache[WM9090_RIGHT_OUTPUT_VOLUME] |=
                WM9090_HPOUT1_VU | WM9090_HPOUT1R_ZC;
 
-       wm9090->reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
+       reg_cache[WM9090_CLOCKING_1] |= WM9090_TOCLK_ENA;
 
        wm9090_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
 
index 75ed6491222d1d283d69d5881560a823c958d253..c721502833bcbf424855c87bcf1fddf2805bbafe 100644 (file)
@@ -944,6 +944,9 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
                case SND_SOC_DAPM_STREAM_RESUME:
                        sys_power = 1;
                        break;
+               case SND_SOC_DAPM_STREAM_STOP:
+                       sys_power = !!codec->active;
+                       break;
                case SND_SOC_DAPM_STREAM_SUSPEND:
                        sys_power = 0;
                        break;
index 44a47e13bd673eb362f956b80bd02adbec367d45..c49837de7d3f74eb9254d83e4f6457b11ae38c17 100644 (file)
@@ -36,7 +36,6 @@ static const struct option options[] = {
 
 static int __cmd_buildid_list(void)
 {
-       int err = -1;
        struct perf_session *session;
 
        session = perf_session__new(input_name, O_RDONLY, force, false);
@@ -49,7 +48,7 @@ static int __cmd_buildid_list(void)
        perf_session__fprintf_dsos_buildid(session, stdout, with_hits);
 
        perf_session__delete(session);
-       return err;
+       return 0;
 }
 
 int cmd_buildid_list(int argc, const char **argv, const char *prefix __used)
index 2e000c068cc5a377d87923bb302a383abafd3a33..add163c9f0e7d4db3fe01afe704a72c5a923597b 100644 (file)
@@ -249,6 +249,11 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
             !params.show_lines))
                usage_with_options(probe_usage, options);
 
+       /*
+        * Only consider the user's kernel image path if given.
+        */
+       symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
+
        if (params.list_events) {
                if (params.mod_events) {
                        pr_err("  Error: Don't use --list with --add/--del.\n");
index 64a85bafde63a1c6f05451a32b31eec521c799d9..7cba0551a56550888c98ff1a933fd6bec8ab9ca0 100644 (file)
@@ -265,15 +265,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
                          const char *name, bool is_kallsyms)
 {
        const size_t size = PATH_MAX;
-       char *filename = malloc(size),
+       char *realname = realpath(name, NULL),
+            *filename = malloc(size),
             *linkname = malloc(size), *targetname;
        int len, err = -1;
 
-       if (filename == NULL || linkname == NULL)
+       if (realname == NULL || filename == NULL || linkname == NULL)
                goto out_free;
 
        len = snprintf(filename, size, "%s%s%s",
-                      debugdir, is_kallsyms ? "/" : "", name);
+                      debugdir, is_kallsyms ? "/" : "", realname);
        if (mkdir_p(filename, 0755))
                goto out_free;
 
@@ -283,7 +284,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
                if (is_kallsyms) {
                         if (copyfile("/proc/kallsyms", filename))
                                goto out_free;
-               } else if (link(name, filename) && copyfile(name, filename))
+               } else if (link(realname, filename) && copyfile(name, filename))
                        goto out_free;
        }
 
@@ -300,6 +301,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
        if (symlink(targetname, linkname) == 0)
                err = 0;
 out_free:
+       free(realname);
        free(filename);
        free(linkname);
        return err;
index 2022e87409942ca4b0d133c3f889e41178a663d1..76bcc35cf9b143c8a6661f74aeb349004363306d 100644 (file)
@@ -356,7 +356,7 @@ static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask,
 
 static size_t ipchain__fprintf_graph(FILE *fp, struct callchain_list *chain,
                                     int depth, int depth_mask, int period,
-                                    u64 total_samples, int hits,
+                                    u64 total_samples, u64 hits,
                                     int left_margin)
 {
        int i;
index 3b6a5297bf16cd5a318273bc0a9bf198734a0cfe..61191c6cbe7a8d04af83e1af5426029a73bc7b99 100644 (file)
@@ -114,6 +114,8 @@ static struct symbol *__find_kernel_function_by_name(const char *name,
 const char *kernel_get_module_path(const char *module)
 {
        struct dso *dso;
+       struct map *map;
+       const char *vmlinux_name;
 
        if (module) {
                list_for_each_entry(dso, &machine.kernel_dsos, node) {
@@ -123,10 +125,17 @@ const char *kernel_get_module_path(const char *module)
                }
                pr_debug("Failed to find module %s.\n", module);
                return NULL;
+       }
+
+       map = machine.vmlinux_maps[MAP__FUNCTION];
+       dso = map->dso;
+
+       vmlinux_name = symbol_conf.vmlinux_name;
+       if (vmlinux_name) {
+               if (dso__load_vmlinux(dso, map, vmlinux_name, NULL) <= 0)
+                       return NULL;
        } else {
-               dso = machine.vmlinux_maps[MAP__FUNCTION]->dso;
-               if (dso__load_vmlinux_path(dso,
-                        machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) {
+               if (dso__load_vmlinux_path(dso, map, NULL) <= 0) {
                        pr_debug("Failed to load kernel map.\n");
                        return NULL;
                }
index 3991d73d1cff9164cb23fb4aae3169af97abfe77..ddf4d45563218ad9e2d8971d32f2a8f25097c502 100644 (file)
@@ -117,28 +117,6 @@ static void line_list__free(struct list_head *head)
 }
 
 /* Dwarf FL wrappers */
-
-static int __linux_kernel_find_elf(Dwfl_Module *mod,
-                                  void **userdata,
-                                  const char *module_name,
-                                  Dwarf_Addr base,
-                                  char **file_name, Elf **elfp)
-{
-       int fd;
-       const char *path = kernel_get_module_path(module_name);
-
-       if (path) {
-               fd = open(path, O_RDONLY);
-               if (fd >= 0) {
-                       *file_name = strdup(path);
-                       return fd;
-               }
-       }
-       /* If failed, try to call standard method */
-       return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
-                                         file_name, elfp);
-}
-
 static char *debuginfo_path;   /* Currently dummy */
 
 static const Dwfl_Callbacks offline_callbacks = {
@@ -151,14 +129,6 @@ static const Dwfl_Callbacks offline_callbacks = {
        .find_elf = dwfl_build_id_find_elf,
 };
 
-static const Dwfl_Callbacks kernel_callbacks = {
-       .find_debuginfo = dwfl_standard_find_debuginfo,
-       .debuginfo_path = &debuginfo_path,
-
-       .find_elf = __linux_kernel_find_elf,
-       .section_address = dwfl_linux_kernel_module_section_address,
-};
-
 /* Get a Dwarf from offline image */
 static Dwarf *dwfl_init_offline_dwarf(int fd, Dwfl **dwflp, Dwarf_Addr *bias)
 {
@@ -185,6 +155,38 @@ error:
        return dbg;
 }
 
+#if _ELFUTILS_PREREQ(0, 148)
+/* This method is buggy if elfutils is older than 0.148 */
+static int __linux_kernel_find_elf(Dwfl_Module *mod,
+                                  void **userdata,
+                                  const char *module_name,
+                                  Dwarf_Addr base,
+                                  char **file_name, Elf **elfp)
+{
+       int fd;
+       const char *path = kernel_get_module_path(module_name);
+
+       pr_debug2("Use file %s for %s\n", path, module_name);
+       if (path) {
+               fd = open(path, O_RDONLY);
+               if (fd >= 0) {
+                       *file_name = strdup(path);
+                       return fd;
+               }
+       }
+       /* If failed, try to call standard method */
+       return dwfl_linux_kernel_find_elf(mod, userdata, module_name, base,
+                                         file_name, elfp);
+}
+
+static const Dwfl_Callbacks kernel_callbacks = {
+       .find_debuginfo = dwfl_standard_find_debuginfo,
+       .debuginfo_path = &debuginfo_path,
+
+       .find_elf = __linux_kernel_find_elf,
+       .section_address = dwfl_linux_kernel_module_section_address,
+};
+
 /* Get a Dwarf from live kernel image */
 static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
                                          Dwarf_Addr *bias)
@@ -205,11 +207,34 @@ static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr, Dwfl **dwflp,
        dbg = dwfl_addrdwarf(*dwflp, addr, bias);
        /* Here, check whether we could get a real dwarf */
        if (!dbg) {
+               pr_debug("Failed to find kernel dwarf at %lx\n",
+                        (unsigned long)addr);
                dwfl_end(*dwflp);
                *dwflp = NULL;
        }
        return dbg;
 }
+#else
+/* With older elfutils, this just support kernel module... */
+static Dwarf *dwfl_init_live_kernel_dwarf(Dwarf_Addr addr __used, Dwfl **dwflp,
+                                         Dwarf_Addr *bias)
+{
+       int fd;
+       const char *path = kernel_get_module_path("kernel");
+
+       if (!path) {
+               pr_err("Failed to find vmlinux path\n");
+               return NULL;
+       }
+
+       pr_debug2("Use file %s for debuginfo\n", path);
+       fd = open(path, O_RDONLY);
+       if (fd < 0)
+               return NULL;
+
+       return dwfl_init_offline_dwarf(fd, dwflp, bias);
+}
+#endif
 
 /* Dwarf wrappers */
 
index 0409fc7c0058809f01da646c4d5ee98c21f69b1d..8fc0bd3a3a4a6bd3f816a6619cc1de0793a98caa 100644 (file)
@@ -259,7 +259,7 @@ static bool __match_glob(const char *str, const char *pat, bool ignore_space)
                if (!*pat)      /* Tail wild card matches all */
                        return true;
                while (*str)
-                       if (strglobmatch(str++, pat))
+                       if (__match_glob(str++, pat, ignore_space))
                                return true;
        }
        return !*str && !*pat;
index d628c8d1cf5ec11111ab3b750da0d14f6d8fff7f..439ab947daf4af9da352caac290d372ce23846ac 100644 (file)
@@ -1780,8 +1780,8 @@ out_failure:
        return -1;
 }
 
-static int dso__load_vmlinux(struct dso *self, struct map *map,
-                            const char *vmlinux, symbol_filter_t filter)
+int dso__load_vmlinux(struct dso *self, struct map *map,
+                     const char *vmlinux, symbol_filter_t filter)
 {
        int err = -1, fd;
 
index 038f2201ee09579ca3f460d9f59576770ea477d2..6c6eafdb932dacefd29c3ea21e5bef90a80cc9a9 100644 (file)
@@ -166,6 +166,8 @@ void dso__sort_by_name(struct dso *self, enum map_type type);
 struct dso *__dsos__findnew(struct list_head *head, const char *name);
 
 int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
+int dso__load_vmlinux(struct dso *self, struct map *map,
+                     const char *vmlinux, symbol_filter_t filter);
 int dso__load_vmlinux_path(struct dso *self, struct map *map,
                           symbol_filter_t filter);
 int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,