Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 2 Dec 2011 16:10:51 +0000 (08:10 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 2 Dec 2011 16:10:51 +0000 (08:10 -0800)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: hda - Fix S3/S4 problem on machines with VREF-pin mute-LED
  ALSA: hda_intel - revert a quirk that affect VIA chipsets
  ALSA: hda - Avoid touching mute-VREF pin for IDT codecs
  firmware: Sigma: Fix endianess issues
  firmware: Sigma: Skip header during CRC generation
  firmware: Sigma: Prevent out of bounds memory access
  ALSA: usb-audio - Support for Roland GAIA SH-01 Synthesizer
  ASoC: Supply dcs_codes for newer WM1811 revisions
  ASoC: Error out if we can't generate a LRCLK at all for WM8994
  ASoC: Correct name of Speyside Main Speaker widget
  ASoC: skip resume of soc-audio devices without codecs
  ASoC: cs42l51: Fix off-by-one for reg_cache_size
  ASoC: drop support for PlayPaq with WM8510
  ASoC: mpc8610: tell the CS4270 codec that it's the master
  ASoC: cs4720: use snd_soc_cache_sync()
  ASoC: SAMSUNG: Fix build error
  ASoC: max9877: Update register if either val or val2 is changed
  ASoC: Fix wrong define for AD1836_ADC_WORD_OFFSET

970 files changed:
.mailmap
Documentation/ABI/testing/sysfs-block
Documentation/DocBook/drm.tmpl
Documentation/DocBook/uio-howto.tmpl
Documentation/blockdev/cciss.txt
Documentation/cgroups/freezer-subsystem.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/filesystems/btrfs.txt
Documentation/i2c/ten-bit-addresses
Documentation/networking/ip-sysctl.txt
Documentation/power/devices.txt
Documentation/power/runtime_pm.txt
Documentation/serial/serial-rs485.txt
Kbuild
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/boot/Makefile
arch/arm/boot/dts/tegra-ventana.dts
arch/arm/common/gic.c
arch/arm/common/pl330.c
arch/arm/configs/at91cap9_defconfig [new file with mode: 0644]
arch/arm/configs/at91cap9adk_defconfig [deleted file]
arch/arm/configs/at91rm9200_defconfig
arch/arm/configs/at91sam9260_defconfig [new file with mode: 0644]
arch/arm/configs/at91sam9260ek_defconfig [deleted file]
arch/arm/configs/at91sam9g20_defconfig [new file with mode: 0644]
arch/arm/configs/at91sam9g20ek_defconfig [deleted file]
arch/arm/configs/at91sam9g45_defconfig
arch/arm/configs/at91sam9rl_defconfig [new file with mode: 0644]
arch/arm/configs/at91sam9rlek_defconfig [deleted file]
arch/arm/configs/ezx_defconfig
arch/arm/configs/imote2_defconfig
arch/arm/configs/magician_defconfig
arch/arm/configs/omap1_defconfig
arch/arm/configs/u300_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/configs/zeus_defconfig
arch/arm/include/asm/hardware/cache-l2x0.h
arch/arm/include/asm/mach/arch.h
arch/arm/include/asm/pmu.h
arch/arm/include/asm/topology.h
arch/arm/include/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kernel/entry-armv.S
arch/arm/kernel/head.S
arch/arm/kernel/kprobes-arm.c
arch/arm/kernel/kprobes-test-arm.c
arch/arm/kernel/kprobes-test-thumb.c
arch/arm/kernel/kprobes-test.h
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/pmu.c
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/kernel/topology.c
arch/arm/lib/bitops.h
arch/arm/lib/changebit.S
arch/arm/lib/clearbit.S
arch/arm/lib/setbit.S
arch/arm/lib/testchangebit.S
arch/arm/lib/testclearbit.S
arch/arm/lib/testsetbit.S
arch/arm/mach-at91/at91cap9_devices.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/include/mach/vmalloc.h
arch/arm/mach-bcmring/core.c
arch/arm/mach-bcmring/dma.c
arch/arm/mach-exynos/cpuidle.c
arch/arm/mach-highbank/highbank.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile.boot
arch/arm/mach-imx/clock-imx6q.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-imx/src.c
arch/arm/mach-mmp/gplugd.c
arch/arm/mach-mmp/include/mach/gpio-pxa.h
arch/arm/mach-msm/Makefile
arch/arm/mach-msm/board-msm7x30.c
arch/arm/mach-msm/board-msm8960.c
arch/arm/mach-msm/board-msm8x60.c
arch/arm/mach-msm/scm.c
arch/arm/mach-mx5/clock-mx51-mx53.c
arch/arm/mach-mx5/cpu.c
arch/arm/mach-mx5/mm.c
arch/arm/mach-mxs/clock-mx28.c
arch/arm/mach-mxs/mach-mx28evk.c
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/clock.h
arch/arm/mach-omap1/clock_data.c
arch/arm/mach-omap1/devices.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/display.c
arch/arm/mach-omap2/display.h [new file with mode: 0644]
arch/arm/mach-omap2/io.h [deleted file]
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_3xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_common_data.c
arch/arm/mach-omap2/omap_hwmod_common_data.h
arch/arm/mach-omap2/omap_l3_noc.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/smartreflex.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/twl-common.h
arch/arm/mach-picoxcell/include/mach/debug-macro.S
arch/arm/mach-pxa/balloon3.c
arch/arm/mach-pxa/colibri-pxa320.c
arch/arm/mach-pxa/gumstix.c
arch/arm/mach-pxa/include/mach/palm27x.h
arch/arm/mach-pxa/palm27x.c
arch/arm/mach-pxa/palmtc.c
arch/arm/mach-pxa/vpac270.c
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-shmobile/Makefile
arch/arm/mach-shmobile/board-ag5evm.c
arch/arm/mach-shmobile/board-ap4evb.c
arch/arm/mach-shmobile/board-kota2.c
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/cpuidle.c
arch/arm/mach-shmobile/include/mach/common.h
arch/arm/mach-shmobile/include/mach/sh73a0.h
arch/arm/mach-shmobile/pfc-sh7367.c
arch/arm/mach-shmobile/pfc-sh7372.c
arch/arm/mach-shmobile/pfc-sh7377.c
arch/arm/mach-shmobile/pfc-sh73a0.c
arch/arm/mach-shmobile/pm-sh7372.c
arch/arm/mach-shmobile/pm_runtime.c [deleted file]
arch/arm/mach-tegra/board-dt.c
arch/arm/mach-tegra/board-harmony-pinmux.c
arch/arm/mach-tegra/board-paz00-pinmux.c
arch/arm/mach-tegra/board-seaboard-pinmux.c
arch/arm/mach-tegra/board-trimslice-pinmux.c
arch/arm/mach-w90x900/dev.c
arch/arm/mach-w90x900/include/mach/mfp.h
arch/arm/mach-w90x900/include/mach/nuc900_spi.h
arch/arm/mach-w90x900/mfp.c
arch/arm/mm/cache-l2x0.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mmap.c
arch/arm/plat-mxc/Kconfig
arch/arm/plat-mxc/avic.c
arch/arm/plat-mxc/gic.c
arch/arm/plat-mxc/include/mach/common.h
arch/arm/plat-mxc/include/mach/entry-macro.S
arch/arm/plat-mxc/include/mach/mxc.h
arch/arm/plat-mxc/include/mach/system.h
arch/arm/plat-mxc/system.c
arch/arm/plat-mxc/tzic.c
arch/arm/plat-omap/include/plat/clock.h
arch/arm/plat-omap/include/plat/common.h
arch/arm/plat-s3c24xx/cpu-freq-debugfs.c
arch/arm/plat-s5p/sysmmu.c
arch/arm/plat-samsung/include/plat/gpio-cfg.h
arch/arm/plat-samsung/pd.c
arch/arm/plat-samsung/pwm.c
arch/arm/tools/mach-types
arch/blackfin/include/asm/bfin_serial.h
arch/blackfin/mach-bf518/boards/ezbrd.c
arch/blackfin/mach-bf518/boards/tcm-bf518.c
arch/blackfin/mach-bf527/boards/ad7160eval.c
arch/blackfin/mach-bf527/boards/cm_bf527.c
arch/blackfin/mach-bf527/boards/ezbrd.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf527/boards/tll6527m.c
arch/blackfin/mach-bf533/boards/H8606.c
arch/blackfin/mach-bf533/boards/blackstamp.c
arch/blackfin/mach-bf533/boards/cm_bf533.c
arch/blackfin/mach-bf533/boards/ezkit.c
arch/blackfin/mach-bf533/boards/ip0x.c
arch/blackfin/mach-bf533/boards/stamp.c
arch/blackfin/mach-bf537/boards/cm_bf537e.c
arch/blackfin/mach-bf537/boards/cm_bf537u.c
arch/blackfin/mach-bf537/boards/dnp5370.c
arch/blackfin/mach-bf537/boards/minotaur.c
arch/blackfin/mach-bf537/boards/pnav10.c
arch/blackfin/mach-bf537/boards/stamp.c
arch/blackfin/mach-bf537/boards/tcm_bf537.c
arch/blackfin/mach-bf538/boards/ezkit.c
arch/blackfin/mach-bf548/boards/cm_bf548.c
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf561/boards/acvilon.c
arch/blackfin/mach-bf561/boards/cm_bf561.c
arch/blackfin/mach-bf561/boards/ezkit.c
arch/blackfin/mach-bf561/boards/tepla.c
arch/cris/arch-v10/drivers/Kconfig
arch/cris/arch-v32/drivers/Kconfig
arch/m68k/Kconfig
arch/m68k/Kconfig.bus
arch/m68k/Kconfig.devices
arch/m68k/amiga/amiints.c
arch/m68k/amiga/cia.c
arch/m68k/apollo/dn_ints.c
arch/m68k/atari/ataints.c
arch/m68k/bvme6000/config.c
arch/m68k/hp300/time.c
arch/m68k/include/asm/hardirq.h
arch/m68k/include/asm/irq.h
arch/m68k/include/asm/macintosh.h
arch/m68k/include/asm/q40ints.h
arch/m68k/kernel/Makefile
arch/m68k/kernel/entry_mm.S
arch/m68k/kernel/ints.c
arch/m68k/mac/baboon.c
arch/m68k/mac/iop.c
arch/m68k/mac/macints.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/q40ints.c
arch/m68k/sun3/sun3ints.c
arch/microblaze/include/asm/namei.h [deleted file]
arch/mips/Makefile
arch/mips/cavium-octeon/flash_setup.c
arch/mips/cavium-octeon/smp.c
arch/mips/emma/common/prom.c
arch/mips/include/asm/mach-bcm47xx/gpio.h
arch/mips/include/asm/unistd.h
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cpufreq/loongson2_clock.c
arch/mips/kernel/scall32-o32.S
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-o32.S
arch/mips/kernel/traps.c
arch/mips/lantiq/clk.c
arch/mips/lantiq/devices.c
arch/mips/lantiq/prom.c
arch/mips/lantiq/setup.c
arch/mips/lantiq/xway/clk-ase.c
arch/mips/lantiq/xway/clk-xway.c
arch/mips/lantiq/xway/devices.c
arch/mips/lantiq/xway/dma.c
arch/mips/lantiq/xway/gpio.c
arch/mips/lantiq/xway/gpio_ebu.c
arch/mips/lantiq/xway/gpio_stp.c
arch/mips/lantiq/xway/prom-ase.c
arch/mips/lantiq/xway/prom-xway.c
arch/mips/lantiq/xway/reset.c
arch/mips/nxp/pnx8550/common/pci.c [deleted file]
arch/mips/nxp/pnx8550/common/setup.c [deleted file]
arch/mips/pci/pci-alchemy.c
arch/mips/pci/pci-lantiq.c
arch/mips/pmc-sierra/yosemite/prom.c
arch/powerpc/Kconfig
arch/powerpc/Makefile
arch/powerpc/boot/dts/charon.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1023rds.dts
arch/powerpc/configs/52xx/tqm5200_defconfig
arch/powerpc/configs/ppc44x_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/include/asm/atomic.h
arch/powerpc/include/asm/bitops.h
arch/powerpc/include/asm/floppy.h
arch/powerpc/include/asm/futex.h
arch/powerpc/include/asm/kvm.h
arch/powerpc/include/asm/kvm_book3s.h
arch/powerpc/include/asm/lv1call.h
arch/powerpc/include/asm/reg_booke.h
arch/powerpc/include/asm/sections.h
arch/powerpc/include/asm/synch.h
arch/powerpc/include/asm/xics.h
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/jump_label.c
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/traps.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_pr.c
arch/powerpc/kvm/powerpc.c
arch/powerpc/lib/feature-fixups.c
arch/powerpc/mm/hugetlbpage.c
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/platforms/52xx/mpc5200_simple.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/p3060_qds.c
arch/powerpc/platforms/Kconfig
arch/powerpc/platforms/cell/beat.c
arch/powerpc/platforms/cell/celleb_scc_pciex.c
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/pmu.c
arch/powerpc/platforms/cell/spu_base.c
arch/powerpc/platforms/powermac/pic.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/ps3/device-init.c
arch/powerpc/platforms/ps3/interrupt.c
arch/powerpc/platforms/ps3/platform.h
arch/powerpc/platforms/ps3/repository.c
arch/powerpc/platforms/ps3/smp.c
arch/powerpc/sysdev/ehv_pic.c
arch/powerpc/sysdev/fsl_lbc.c
arch/powerpc/sysdev/fsl_rio.c
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/ppc4xx_soc.c
arch/powerpc/sysdev/qe_lib/qe.c
arch/powerpc/sysdev/xics/xics-common.c
arch/s390/Kconfig
arch/s390/crypto/crypt_s390.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/timex.h
arch/s390/include/asm/unistd.h
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/early.c
arch/s390/kernel/setup.c
arch/s390/kernel/syscalls.S
arch/s390/kernel/topology.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/diag.c
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/mm/fault.c
arch/sh/include/asm/page.h
arch/sh/include/asm/unistd_32.h
arch/sh/include/asm/unistd_64.h
arch/sh/kernel/cpu/sh2a/setup-sh7203.c
arch/sh/kernel/syscalls_32.S
arch/sh/kernel/syscalls_64.S
arch/sparc/include/asm/pgtable_32.h
arch/sparc/include/asm/pgtable_64.h
arch/sparc/include/asm/unistd.h
arch/sparc/kernel/entry.h
arch/sparc/kernel/module.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sigutil_64.c
arch/sparc/kernel/systbls_32.S
arch/sparc/kernel/systbls_64.S
arch/sparc/mm/Makefile
arch/sparc/mm/generic_32.c [deleted file]
arch/sparc/mm/generic_64.c [deleted file]
arch/unicore32/Kconfig
arch/unicore32/Kconfig.debug
arch/unicore32/boot/compressed/Makefile
arch/unicore32/include/asm/bitops.h
arch/unicore32/include/asm/processor.h
arch/unicore32/kernel/ksyms.c
arch/unicore32/lib/findbit.S
arch/x86/include/asm/apic.h
arch/x86/include/asm/mach_traps.h
arch/x86/include/asm/mce.h
arch/x86/include/asm/mrst.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/alternative.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/cpu/mcheck/mce-inject.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/kvmclock.c
arch/x86/kernel/nmi.c
arch/x86/kernel/setup.c
arch/x86/kernel/x86_init.c
arch/x86/kvm/vmx.c
arch/x86/platform/ce4100/ce4100.c
arch/x86/platform/mrst/mrst.c
arch/x86/platform/mrst/vrtc.c
arch/x86/um/asm/processor.h
arch/x86/xen/enlighten.c
arch/x86/xen/grant-table.c
block/blk-core.c
block/blk-map.c
block/genhd.c
crypto/ablkcipher.c
crypto/aead.c
crypto/ahash.c
crypto/blkcipher.c
crypto/crypto_user.c
crypto/pcompress.c
crypto/rng.c
crypto/shash.c
drivers/acpi/apei/erst.c
drivers/acpi/processor_idle.c
drivers/ata/ahci.c
drivers/ata/ahci_platform.c
drivers/ata/libata-eh.c
drivers/ata/libata-pmp.c
drivers/ata/libata-scsi.c
drivers/ata/libata-sff.c
drivers/ata/pata_of_platform.c
drivers/ata/sata_sis.c
drivers/base/core.c
drivers/base/node.c
drivers/base/power/clock_ops.c
drivers/base/power/main.c
drivers/base/power/opp.c
drivers/base/power/qos.c
drivers/block/cciss.c
drivers/block/cciss_scsi.c
drivers/block/loop.c
drivers/block/paride/pg.c
drivers/bluetooth/btusb.c
drivers/char/agp/intel-gtt.c
drivers/char/random.c
drivers/cpufreq/db8500-cpufreq.c
drivers/crypto/mv_cesa.c
drivers/devfreq/Kconfig
drivers/devfreq/devfreq.c
drivers/edac/mpc85xx_edac.c
drivers/firmware/dmi_scan.c
drivers/firmware/efivars.c
drivers/gpio/gpio-omap.c
drivers/gpio/gpio-pca953x.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_crtc_helper.c
drivers/gpu/drm/drm_debugfs.c
drivers/gpu/drm/drm_drv.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/exynos/exynos_drm_buf.c
drivers/gpu/drm/exynos/exynos_drm_buf.h
drivers/gpu/drm/exynos/exynos_drm_connector.c
drivers/gpu/drm/exynos/exynos_drm_crtc.c
drivers/gpu/drm/exynos/exynos_drm_crtc.h
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_drv.h
drivers/gpu/drm/exynos/exynos_drm_encoder.c
drivers/gpu/drm/exynos/exynos_drm_encoder.h
drivers/gpu/drm/exynos/exynos_drm_fb.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gem.h
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/nouveau/nouveau_bios.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_channel.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_i2c.c
drivers/gpu/drm/nouveau/nouveau_perf.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv40_pm.c
drivers/gpu/drm/nouveau/nv50_graph.c
drivers/gpu/drm/nouveau/nv50_grctx.c
drivers/gpu/drm/nouveau/nv50_vram.c
drivers/gpu/drm/nouveau/nvc0_graph.c
drivers/gpu/drm/nouveau/nvc0_grctx.c
drivers/gpu/drm/nouveau/nvc0_vram.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreen_cs.c
drivers/gpu/drm/radeon/r300.c
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_asic.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_benchmark.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_legacy_crtc.c
drivers/gpu/drm/radeon/radeon_pm.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
drivers/gpu/vga/vgaarb.c
drivers/hwmon/Kconfig
drivers/hwmon/ad7314.c
drivers/hwmon/ads7871.c
drivers/hwmon/exynos4_tmu.c
drivers/hwmon/gpio-fan.c
drivers/hwmon/jz4740-hwmon.c
drivers/hwmon/ntc_thermistor.c
drivers/hwmon/s3c-hwmon.c
drivers/hwmon/sch5627.c
drivers/hwmon/sch5636.c
drivers/hwmon/twl4030-madc-hwmon.c
drivers/hwmon/ultra45_env.c
drivers/hwmon/wm831x-hwmon.c
drivers/hwmon/wm8350-hwmon.c
drivers/hwspinlock/u8500_hsem.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/busses/i2c-nuc900.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ide/cy82c693.c
drivers/ide/icside.c
drivers/ide/ide-cd.c
drivers/ide/ide-floppy.c
drivers/ide/ide-tape.c
drivers/ide/piix.c
drivers/ide/triflex.c
drivers/infiniband/core/addr.c
drivers/infiniband/hw/cxgb3/iwch_cm.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/qib/qib_qsfp.c
drivers/infiniband/ulp/ipoib/ipoib_ib.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/input/mouse/elantech.c
drivers/input/serio/ams_delta_serio.c
drivers/input/serio/i8042-x86ia64io.h
drivers/iommu/omap-iommu-debug.c
drivers/iommu/omap-iovmm.c
drivers/isdn/divert/divert_procfs.c
drivers/isdn/i4l/isdn_net.c
drivers/leds/led-class.c
drivers/macintosh/via-macii.c
drivers/macintosh/via-maciisi.c
drivers/md/raid5.c
drivers/media/dvb/dvb-usb/mxl111sf-i2c.c
drivers/media/dvb/dvb-usb/mxl111sf-phy.c
drivers/media/video/s5k6aa.c
drivers/media/video/s5p-mfc/s5p_mfc_dec.c
drivers/media/video/s5p-mfc/s5p_mfc_enc.c
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/v4l2-ctrls.c
drivers/media/video/v4l2-event.c
drivers/media/video/videobuf2-core.c
drivers/mfd/ab5500-core.c
drivers/mfd/ab5500-debugfs.c
drivers/misc/Kconfig
drivers/misc/ad525x_dpot.h
drivers/misc/carma/carma-fpga-program.c
drivers/misc/carma/carma-fpga.c
drivers/misc/eeprom/Kconfig
drivers/misc/pch_phub.c
drivers/misc/spear13xx_pcie_gadget.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mtd/maps/bcm963xx-flash.c
drivers/net/Kconfig
drivers/net/arcnet/Kconfig
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/sja1000/peak_pci.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_reg.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/cadence/Kconfig
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/freescale/Kconfig
drivers/net/ethernet/ibm/ehea/ehea.h
drivers/net/ethernet/ibm/ehea/ehea_main.c
drivers/net/ethernet/ibm/iseries_veth.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/jme.h
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/marvell/sky2.h
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_param.c
drivers/net/ethernet/qlogic/qlge/qlge.h
drivers/net/ethernet/rdc/r6040.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/stmicro/stmmac/dwmac1000_dma.c
drivers/net/ethernet/stmicro/stmmac/dwmac100_dma.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/hippi/Kconfig
drivers/net/phy/Kconfig
drivers/net/usb/asix.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/lg-vl600.c
drivers/net/usb/smsc75xx.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/b43/xmit.c
drivers/net/wireless/b43/xmit.h
drivers/net/wireless/brcm80211/brcmsmac/dma.c
drivers/net/wireless/iwlwifi/iwl-trans-pcie.c
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/if_spi.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/p54/p54spi.c
drivers/net/wireless/prism54/isl_ioctl.c
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rtlwifi/ps.c
drivers/net/wireless/wl12xx/scan.c
drivers/net/xen-netback/netback.c
drivers/of/irq.c
drivers/pci/Kconfig
drivers/pci/hotplug/acpiphp_glue.c
drivers/pci/hotplug/pciehp_ctrl.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_hpc.c
drivers/pinctrl/Kconfig
drivers/platform/x86/Kconfig
drivers/platform/x86/dell-laptop.c
drivers/ps3/ps3-vuart.c
drivers/ps3/ps3stor_lib.c
drivers/regulator/aat2870-regulator.c
drivers/regulator/core.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/twl-regulator.c
drivers/rtc/rtc-mrst.c
drivers/rtc/rtc-puv3.c
drivers/s390/char/zcore.c
drivers/s390/crypto/ap_bus.c
drivers/s390/net/Kconfig
drivers/s390/net/lcs.c
drivers/s390/net/netiucv.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/qeth_l3_sys.c
drivers/scsi/aacraid/linit.c
drivers/scsi/hpsa.c
drivers/scsi/mpt2sas/mpt2sas_scsih.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/sh/Makefile
drivers/sh/clk/core.c
drivers/sh/pm_runtime.c [new file with mode: 0644]
drivers/spi/spi-atmel.c
drivers/spi/spi-nuc900.c
drivers/spi/spi-pl022.c
drivers/staging/et131x/Kconfig
drivers/staging/et131x/et131x.c
drivers/staging/iio/industrialio-core.c
drivers/staging/media/as102/as102_drv.c
drivers/staging/media/as102/as102_drv.h
drivers/staging/octeon/ethernet-tx.c
drivers/staging/slicoss/Kconfig
drivers/tty/hvc/hvc_dcc.c
drivers/tty/n_gsm.c
drivers/tty/serial/Kconfig
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/crisv10.c
drivers/tty/serial/mfd.c
drivers/tty/serial/pch_uart.c
drivers/tty/serial/sh-sci.c
drivers/tty/tty_ldisc.c
drivers/usb/class/cdc-acm.c
drivers/usb/core/hub.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/ci13xxx_msm.c
drivers/usb/gadget/ci13xxx_udc.c
drivers/usb/gadget/f_mass_storage.c
drivers/usb/gadget/f_midi.c
drivers/usb/gadget/f_phonet.c
drivers/usb/gadget/file_storage.c
drivers/usb/gadget/fsl_udc_core.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/pch_udc.c
drivers/usb/gadget/r8a66597-udc.c
drivers/usb/gadget/udc-core.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-xls.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-pci.c
drivers/usb/host/ohci.h
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/musb/Kconfig
drivers/usb/musb/am35x.c
drivers/usb/musb/da8xx.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_gadget.c
drivers/usb/renesas_usbhs/common.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/renesas_usbhs/mod.h
drivers/usb/renesas_usbhs/mod_gadget.c
drivers/usb/renesas_usbhs/mod_host.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/storage/ene_ub6250.c
drivers/usb/storage/protocol.c
drivers/video/da8xx-fb.c
drivers/video/omap/dispc.c
drivers/video/omap2/dss/dispc.c
drivers/video/omap2/dss/hdmi.c
drivers/video/via/share.h
drivers/virtio/Kconfig
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/adx_wdt.c [deleted file]
drivers/watchdog/s3c2410_wdt.c
drivers/watchdog/wm831x_wdt.c
drivers/xen/balloon.c
drivers/xen/gntalloc.c
drivers/xen/gntdev.c
drivers/xen/xenbus/xenbus_client.c
fs/bio.c
fs/btrfs/backref.c
fs/btrfs/btrfs_inode.h
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/free-space-cache.c
fs/btrfs/inode-map.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/scrub.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/ceph/dir.c
fs/ceph/inode.c
fs/ceph/super.c
fs/dcache.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ext4/balloc.c
fs/ext4/inode.c
fs/ext4/super.c
fs/hfs/trans.c
fs/minix/bitmap.c
fs/minix/inode.c
fs/minix/minix.h
fs/namespace.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/super.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/aops.h
fs/ocfs2/cluster/heartbeat.c
fs/ocfs2/cluster/netdebug.c
fs/ocfs2/cluster/tcp.c
fs/ocfs2/cluster/tcp.h
fs/ocfs2/dir.c
fs/ocfs2/dlm/dlmcommon.h
fs/ocfs2/dlm/dlmdomain.c
fs/ocfs2/dlm/dlmlock.c
fs/ocfs2/dlm/dlmmaster.c
fs/ocfs2/dlm/dlmrecovery.c
fs/ocfs2/dlm/dlmthread.c
fs/ocfs2/dlmglue.c
fs/ocfs2/extent_map.c
fs/ocfs2/extent_map.h
fs/ocfs2/file.c
fs/ocfs2/inode.c
fs/ocfs2/inode.h
fs/ocfs2/ioctl.c
fs/ocfs2/journal.c
fs/ocfs2/journal.h
fs/ocfs2/mmap.c
fs/ocfs2/move_extents.c
fs/ocfs2/ocfs2.h
fs/ocfs2/quota_local.c
fs/ocfs2/slot_map.c
fs/ocfs2/stack_o2cb.c
fs/ocfs2/super.c
fs/ocfs2/xattr.c
fs/proc/base.c
fs/pstore/platform.c
fs/xfs/xfs_aops.c
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_dquot_item.c
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log.h
fs/xfs/xfs_qm.c
fs/xfs/xfs_trans.h
fs/xfs/xfs_vnodeops.c
include/drm/drmP.h
include/drm/drm_mode.h
include/drm/drm_pciids.h
include/drm/exynos_drm.h
include/drm/radeon_drm.h
include/linux/bio.h
include/linux/ceph/osd_client.h
include/linux/clocksource.h
include/linux/devfreq.h
include/linux/device.h
include/linux/fs.h
include/linux/genhd.h
include/linux/hugetlb.h
include/linux/hwspinlock.h
include/linux/i2c.h
include/linux/inet_diag.h
include/linux/init_task.h
include/linux/kvm.h
include/linux/mfd/tps65910.h
include/linux/netdevice.h
include/linux/nfs_fs.h
include/linux/nfs_xdr.h
include/linux/pci-ats.h
include/linux/pci.h
include/linux/pci_ids.h
include/linux/pinctrl/pinctrl.h
include/linux/pkt_sched.h
include/linux/pm.h
include/linux/pm_runtime.h
include/linux/pstore.h
include/linux/sched.h
include/linux/serial.h
include/linux/serial_sci.h
include/linux/sh_clk.h
include/linux/sh_pfc.h
include/linux/virtio_config.h
include/linux/virtio_mmio.h
include/linux/vmalloc.h
include/net/bluetooth/l2cap.h
include/net/cfg80211.h
include/net/dst.h
include/net/dst_ops.h
include/net/inet_sock.h
include/net/inetpeer.h
include/net/netfilter/nf_conntrack_ecache.h
include/net/netns/conntrack.h
include/net/red.h
include/net/route.h
include/video/omapdss.h
include/xen/platform_pci.h
kernel/cgroup_freezer.c
kernel/fork.c
kernel/hrtimer.c
kernel/irq/manage.c
kernel/irq/spurious.c
kernel/power/hibernate.c
kernel/power/main.c
kernel/power/qos.c
kernel/time/clocksource.c
kernel/time/timekeeping.c
mm/backing-dev.c
mm/hugetlb.c
mm/nommu.c
mm/oom_kill.c
mm/page-writeback.c
mm/percpu-vm.c
mm/percpu.c
mm/slub.c
mm/vmalloc.c
net/bluetooth/hci_conn.c
net/bluetooth/l2cap_core.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_stp.c
net/caif/cffrml.c
net/ceph/osd_client.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/neighbour.c
net/core/skbuff.c
net/dccp/ipv4.c
net/decnet/dn_route.c
net/decnet/dn_timer.c
net/ipv4/ah4.c
net/ipv4/devinet.c
net/ipv4/igmp.c
net/ipv4/inet_diag.c
net/ipv4/ip_forward.c
net/ipv4/ip_options.c
net/ipv4/netfilter.c
net/ipv4/netfilter/Kconfig
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/ah6.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_input.c
net/ipv6/ip6_tunnel.c
net/ipv6/ipv6_sockglue.c
net/ipv6/ndisc.c
net/ipv6/netfilter/Kconfig
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/l2tp/l2tp_core.c
net/mac80211/agg-tx.c
net/mac80211/debugfs_sta.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/status.c
net/mac80211/util.c
net/netfilter/Kconfig
net/netfilter/ipset/ip_set_hash_ipport.c
net/netfilter/ipset/ip_set_hash_ipportip.c
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/nf_conntrack_ecache.c
net/netfilter/nf_conntrack_netlink.c
net/netlabel/netlabel_kapi.c
net/rds/Kconfig
net/sched/sch_red.c
net/sched/sch_teql.c
net/sctp/auth.c
net/sunrpc/xprtsock.c
net/unix/af_unix.c
net/wireless/nl80211.c
net/wireless/reg.c
net/wireless/scan.c
net/xfrm/xfrm_policy.c
security/keys/encrypted-keys/Makefile
security/keys/encrypted-keys/encrypted.c
security/keys/encrypted-keys/encrypted.h
security/keys/user_defined.c
security/smack/smackfs.c
sound/ppc/snd_ps3.c
sound/soc/nuc900/nuc900-ac97.c
tools/testing/ktest/ktest.pl
tools/testing/ktest/sample.conf

index a4806f0..9b0d026 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -68,6 +68,7 @@ Juha Yrjola <juha.yrjola@solidboot.com>
 Kay Sievers <kay.sievers@vrfy.org>
 Kenneth W Chen <kenneth.w.chen@intel.com>
 Koushik <raghavendra.koushik@neterion.com>
+Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 Leonid I Ananiev <leonid.i.ananiev@intel.com>
 Linas Vepstas <linas@austin.ibm.com>
 Mark Brown <broonie@sirena.org.uk>
@@ -111,3 +112,4 @@ Uwe Kleine-König <ukl@pengutronix.de>
 Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
 Takashi YOSHII <takashi.yoshii.zj@renesas.com>
+Yusuke Goda <goda.yusuke@renesas.com>
index 2b5d561..c1eb41c 100644 (file)
@@ -206,16 +206,3 @@ Description:
                when a discarded area is read the discard_zeroes_data
                parameter will be set to one. Otherwise it will be 0 and
                the result of reading a discarded area is undefined.
-What:          /sys/block/<disk>/alias
-Date:          Aug 2011
-Contact:       Nao Nishijima <nao.nishijima.xt@hitachi.com>
-Description:
-               A raw device name of a disk does not always point a same disk
-               each boot-up time. Therefore, users have to use persistent
-               device names, which udev creates when the kernel finds a disk,
-               instead of raw device name. However, kernel doesn't show those
-               persistent names on its messages (e.g. dmesg).
-               This file can store an alias of the disk and it would be
-               appeared in kernel messages if it is set. A disk can have an
-               alias which length is up to 255bytes. Users can use alphabets,
-               numbers, "-" and "_" in alias name. This file is writeonce.
index c279158..196b8b9 100644 (file)
@@ -32,7 +32,7 @@
       The Linux DRM layer contains code intended to support the needs
       of complex graphics devices, usually containing programmable
       pipelines well suited to 3D graphics acceleration.  Graphics
-      drivers in the kernel can make use of DRM functions to make
+      drivers in the kernel may make use of DRM functions to make
       tasks like memory management, interrupt handling and DMA easier,
       and provide a uniform interface to applications.
     </para>
       existing drivers.
     </para>
     <para>
-      First, we'll go over some typical driver initialization
+      First, we go over some typical driver initialization
       requirements, like setting up command buffers, creating an
       initial output configuration, and initializing core services.
-      Subsequent sections will cover core internals in more detail,
+      Subsequent sections cover core internals in more detail,
       providing implementation notes and examples.
     </para>
     <para>
@@ -74,7 +74,7 @@
     </para>
     <para>
       The core of every DRM driver is struct drm_driver.  Drivers
-      will typically statically initialize a drm_driver structure,
+      typically statically initialize a drm_driver structure,
       then pass it to drm_init() at load time.
     </para>
 
@@ -88,8 +88,8 @@
     </para>
     <programlisting>
       static struct drm_driver driver = {
-       /* don't use mtrr's here, the Xserver or user space app should
-        * deal with them for intel hardware.
+       /* Don't use MTRRs here; the Xserver or userspace app should
+        * deal with them for Intel hardware.
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP |
     </programlisting>
     <para>
       In the example above, taken from the i915 DRM driver, the driver
-      sets several flags indicating what core features it supports.
-      We'll go over the individual callbacks in later sections.  Since
+      sets several flags indicating what core features it supports;
+      we go over the individual callbacks in later sections.  Since
       flags indicate which features your driver supports to the DRM
       core, you need to set most of them prior to calling drm_init().  Some,
       like DRIVER_MODESET can be set later based on user supplied parameters,
        <term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
        <listitem>
          <para>
-           DRIVER_HAVE_IRQ indicates whether the driver has a IRQ
-           handler, DRIVER_IRQ_SHARED indicates whether the device &amp;
+           DRIVER_HAVE_IRQ indicates whether the driver has an IRQ
+           handler DRIVER_IRQ_SHARED indicates whether the device &amp;
            handler support shared IRQs (note that this is required of
            PCI drivers).
          </para>
        <term>DRIVER_DMA_QUEUE</term>
        <listitem>
          <para>
-           If the driver queues DMA requests and completes them
-           asynchronously, this flag should be set.  Deprecated.
+           Should be set if the driver queues DMA requests and completes them
+           asynchronously.  Deprecated.
          </para>
        </listitem>
       </varlistentry>
     </variablelist>
     <para>
       In this specific case, the driver requires AGP and supports
-      IRQs.  DMA, as we'll see, is handled by device specific ioctls
+      IRQs.  DMA, as discussed later, is handled by device-specific ioctls
       in this case.  It also supports the kernel mode setting APIs, though
       unlike in the actual i915 driver source, this example unconditionally
       exports KMS capability.
       initial output configuration.
     </para>
     <para>
-      Note that the tasks performed at driver load time must not
-      conflict with DRM client requirements.  For instance, if user
+      If compatibility is a concern (e.g. with drivers converted over
+      to the new interfaces from the old ones), care must be taken to
+      prevent device initialization and control that is incompatible with
+      currently active userspace drivers.  For instance, if user
       level mode setting drivers are in use, it would be problematic
       to perform output discovery &amp; configuration at load time.
-      Likewise, if pre-memory management aware user level drivers are
+      Likewise, if user-level drivers unaware of memory management are
       in use, memory management and command buffer setup may need to
-      be omitted.  These requirements are driver specific, and care
+      be omitted.  These requirements are driver-specific, and care
       needs to be taken to keep both old and new applications and
       libraries working.  The i915 driver supports the "modeset"
       module parameter to control whether advanced features are
-      enabled at load time or in legacy fashion.  If compatibility is
-      a concern (e.g. with drivers converted over to the new interfaces
-      from the old ones), care must be taken to prevent incompatible
-      device initialization and control with the currently active
-      userspace drivers.
+      enabled at load time or in legacy fashion.
     </para>
 
     <sect2>
       <title>Driver private &amp; performance counters</title>
       <para>
        The driver private hangs off the main drm_device structure and
-       can be used for tracking various device specific bits of
+       can be used for tracking various device-specific bits of
        information, like register offsets, command buffer status,
        register state for suspend/resume, etc.  At load time, a
-       driver can simply allocate one and set drm_device.dev_priv
-       appropriately; at unload the driver can free it and set
-       drm_device.dev_priv to NULL.
+       driver may simply allocate one and set drm_device.dev_priv
+       appropriately; it should be freed and drm_device.dev_priv set
+       to NULL when the driver is unloaded.
       </para>
       <para>
-       The DRM supports several counters which can be used for rough
+       The DRM supports several counters which may be used for rough
        performance characterization.  Note that the DRM stat counter
        system is not often used by applications, and supporting
        additional counters is completely optional.
        These interfaces are deprecated and should not be used.  If performance
        monitoring is desired, the developer should investigate and
        potentially enhance the kernel perf and tracing infrastructure to export
-       GPU related performance information to performance monitoring
-       tools and applications.
+       GPU related performance information for consumption by performance
+       monitoring tools and applications.
       </para>
     </sect2>
 
     <sect2>
       <title>Configuring the device</title>
       <para>
-       Obviously, device configuration will be device specific.
+       Obviously, device configuration is device-specific.
        However, there are several common operations: finding a
        device's PCI resources, mapping them, and potentially setting
        up an IRQ handler.
       <para>
        Finding &amp; mapping resources is fairly straightforward.  The
        DRM wrapper functions, drm_get_resource_start() and
-       drm_get_resource_len() can be used to find BARs on the given
+       drm_get_resource_len(), may be used to find BARs on the given
        drm_device struct.  Once those values have been retrieved, the
        driver load function can call drm_addmap() to create a new
-       mapping for the BAR in question.  Note you'll probably want a
+       mapping for the BAR in question.  Note that you probably want a
        drm_local_map_t in your driver private structure to track any
        mappings you create.
 <!-- !Fdrivers/gpu/drm/drm_bufs.c drm_get_resource_* -->
       <para>
        if compatibility with other operating systems isn't a concern
        (DRM drivers can run under various BSD variants and OpenSolaris),
-       native Linux calls can be used for the above, e.g. pci_resource_*
+       native Linux calls may be used for the above, e.g. pci_resource_*
        and iomap*/iounmap.  See the Linux device driver book for more
        info.
       </para>
       <para>
-       Once you have a register map, you can use the DRM_READn() and
+       Once you have a register map, you may use the DRM_READn() and
        DRM_WRITEn() macros to access the registers on your device, or
-       use driver specific versions to offset into your MMIO space
-       relative to a driver specific base pointer (see I915_READ for
-       example).
+       use driver-specific versions to offset into your MMIO space
+       relative to a driver-specific base pointer (see I915_READ for
+       an example).
       </para>
       <para>
        If your device supports interrupt generation, you may want to
-       setup an interrupt handler at driver load time as well.  This
+       set up an interrupt handler when the driver is loaded.  This
        is done using the drm_irq_install() function.  If your device
        supports vertical blank interrupts, it should call
        drm_vblank_init() to initialize the core vblank handling code before
       </para>
 <!--!Fdrivers/char/drm/drm_irq.c drm_irq_install-->
       <para>
-       Once your interrupt handler is registered (it'll use your
+       Once your interrupt handler is registered (it uses your
        drm_driver.irq_handler as the actual interrupt handling
        function), you can safely enable interrupts on your device,
        assuming any other state your interrupt handler uses is also
        using the pci_map_rom() call, a convenience function that
        takes care of mapping the actual ROM, whether it has been
        shadowed into memory (typically at address 0xc0000) or exists
-       on the PCI device in the ROM BAR.  Note that once you've
-       mapped the ROM and extracted any necessary information, be
-       sure to unmap it; on many devices the ROM address decoder is
-       shared with other BARs, so leaving it mapped can cause
+       on the PCI device in the ROM BAR.  Note that after the ROM
+       has been mapped and any necessary information has been extracted,
+       it should be unmapped; on many devices, the ROM address decoder is
+       shared with other BARs, so leaving it mapped could cause
        undesired behavior like hangs or memory corruption.
 <!--!Fdrivers/pci/rom.c pci_map_rom-->
       </para>
        should support a memory manager.
       </para>
       <para>
-       If your driver supports memory management (it should!), you'll
+       If your driver supports memory management (it should!), you
        need to set that up at load time as well.  How you initialize
-       it depends on which memory manager you're using, TTM or GEM.
+       it depends on which memory manager you're using: TTM or GEM.
       </para>
       <sect3>
        <title>TTM initialization</title>
          and devices with dedicated video RAM (VRAM), i.e. most discrete
          graphics devices.  If your device has dedicated RAM, supporting
          TTM is desirable.  TTM also integrates tightly with your
-         driver specific buffer execution function.  See the radeon
+         driver-specific buffer execution function.  See the radeon
          driver for examples.
        </para>
        <para>
          created by the memory manager at runtime.  Your global TTM should
          have a type of TTM_GLOBAL_TTM_MEM.  The size field for the global
          object should be sizeof(struct ttm_mem_global), and the init and
-         release hooks should point at your driver specific init and
-         release routines, which will probably eventually call
-         ttm_mem_global_init and ttm_mem_global_release respectively.
+         release hooks should point at your driver-specific init and
+         release routines, which probably eventually call
+         ttm_mem_global_init and ttm_mem_global_release, respectively.
        </para>
        <para>
          Once your global TTM accounting structure is set up and initialized
-         (done by calling ttm_global_item_ref on the global object you
-         just created), you'll need to create a buffer object TTM to
+         by calling ttm_global_item_ref() on it,
+         you need to create a buffer object TTM to
          provide a pool for buffer object allocation by clients and the
          kernel itself.  The type of this object should be TTM_GLOBAL_TTM_BO,
          and its size should be sizeof(struct ttm_bo_global).  Again,
-         driver specific init and release functions can be provided,
-         likely eventually calling ttm_bo_global_init and
-         ttm_bo_global_release, respectively.  Also like the previous
-         object, ttm_global_item_ref is used to create an initial reference
+         driver-specific init and release functions may be provided,
+         likely eventually calling ttm_bo_global_init() and
+         ttm_bo_global_release(), respectively.  Also, like the previous
+         object, ttm_global_item_ref() is used to create an initial reference
          count for the TTM, which will call your initialization function.
        </para>
       </sect3>
          GEM is an alternative to TTM, designed specifically for UMA
          devices.  It has simpler initialization and execution requirements
          than TTM, but has no VRAM management capability.  Core GEM
-         initialization is comprised of a basic drm_mm_init call to create
+         is initialized by calling drm_mm_init() to create
          a GTT DRM MM object, which provides an address space pool for
-         object allocation.  In a KMS configuration, the driver will
-         need to allocate and initialize a command ring buffer following
-         basic GEM initialization.  Most UMA devices have a so-called
+         object allocation.  In a KMS configuration, the driver
+         needs to allocate and initialize a command ring buffer following
+         core GEM initialization.  A UMA device usually has what is called a
          "stolen" memory region, which provides space for the initial
          framebuffer and large, contiguous memory regions required by the
-         device.  This space is not typically managed by GEM, and must
+         device.  This space is not typically managed by GEM, and it must
          be initialized separately into its own DRM MM object.
        </para>
        <para>
-         Initialization will be driver specific, and will depend on
-         the architecture of the device.  In the case of Intel
+         Initialization is driver-specific. In the case of Intel
          integrated graphics chips like 965GM, GEM initialization can
          be done by calling the internal GEM init function,
          i915_gem_do_init().  Since the 965GM is a UMA device
-         (i.e. it doesn't have dedicated VRAM), GEM will manage
+         (i.e. it doesn't have dedicated VRAM), GEM manages
          making regular RAM available for GPU operations.  Memory set
          aside by the BIOS (called "stolen" memory by the i915
-         driver) will be managed by the DRM memrange allocator; the
-         rest of the aperture will be managed by GEM.
+         driver) is managed by the DRM memrange allocator; the
+         rest of the aperture is managed by GEM.
          <programlisting>
            /* Basic memrange allocator for stolen space (aka vram) */
            drm_memrange_init(&amp;dev_priv->vram, 0, prealloc_size);
 <!--!Edrivers/char/drm/drm_memrange.c-->
        </para>
        <para>
-         Once the memory manager has been set up, we can allocate the
+         Once the memory manager has been set up, we may allocate the
          command buffer.  In the i915 case, this is also done with a
          GEM function, i915_gem_init_ringbuffer().
        </para>
     <sect2>
       <title>Output configuration</title>
       <para>
-       The final initialization task is output configuration.  This involves
-       finding and initializing the CRTCs, encoders and connectors
-       for your device, creating an initial configuration and
-       registering a framebuffer console driver.
+       The final initialization task is output configuration.  This involves:
+       <itemizedlist>
+         <listitem>
+           Finding and initializing the CRTCs, encoders, and connectors
+           for the device.
+         </listitem>
+         <listitem>
+           Creating an initial configuration.
+         </listitem>
+         <listitem>
+           Registering a framebuffer console driver.
+         </listitem>
+       </itemizedlist>
       </para>
       <sect3>
        <title>Output discovery and initialization</title>
        <para>
-         Several core functions exist to create CRTCs, encoders and
-         connectors, namely drm_crtc_init(), drm_connector_init() and
+         Several core functions exist to create CRTCs, encoders, and
+         connectors, namely: drm_crtc_init(), drm_connector_init(), and
          drm_encoder_init(), along with several "helper" functions to
          perform common tasks.
        </para>
@@ -555,10 +561,10 @@ void intel_crt_init(struct drm_device *dev)
        </programlisting>
        <para>
          In the example above (again, taken from the i915 driver), a
-         CRT connector and encoder combination is created.  A device
-         specific i2c bus is also created, for fetching EDID data and
+         CRT connector and encoder combination is created.  A device-specific
+         i2c bus is also created for fetching EDID data and
          performing monitor detection.  Once the process is complete,
-         the new connector is registered with sysfs, to make its
+         the new connector is registered with sysfs to make its
          properties available to applications.
        </para>
        <sect4>
@@ -567,12 +573,12 @@ void intel_crt_init(struct drm_device *dev)
            Since many PC-class graphics devices have similar display output
            designs, the DRM provides a set of helper functions to make
            output management easier.  The core helper routines handle
-           encoder re-routing and disabling of unused functions following
-           mode set.  Using the helpers is optional, but recommended for
+           encoder re-routing and the disabling of unused functions following
+           mode setting.  Using the helpers is optional, but recommended for
            devices with PC-style architectures (i.e. a set of display planes
            for feeding pixels to encoders which are in turn routed to
            connectors).  Devices with more complex requirements needing
-           finer grained management can opt to use the core callbacks
+           finer grained management may opt to use the core callbacks
            directly.
          </para>
          <para>
@@ -580,17 +586,25 @@ void intel_crt_init(struct drm_device *dev)
          </para>
        </sect4>
        <para>
-         For each encoder, CRTC and connector, several functions must
-         be provided, depending on the object type.  Encoder objects
-         need to provide a DPMS (basically on/off) function, mode fixup
-         (for converting requested modes into native hardware timings),
-         and prepare, set and commit functions for use by the core DRM
-         helper functions.  Connector helpers need to provide mode fetch and
-         validity functions as well as an encoder matching function for
-         returning an ideal encoder for a given connector.  The core
-         connector functions include a DPMS callback, (deprecated)
-         save/restore routines, detection, mode probing, property handling,
-         and cleanup functions.
+         Each encoder object needs to provide:
+         <itemizedlist>
+           <listitem>
+             A DPMS (basically on/off) function.
+           </listitem>
+           <listitem>
+             A mode-fixup function (for converting requested modes into
+             native hardware timings).
+           </listitem>
+           <listitem>
+             Functions (prepare, set, and commit) for use by the core DRM
+             helper functions.
+           </listitem>
+         </itemizedlist>
+         Connector helpers need to provide functions (mode-fetch, validity,
+         and encoder-matching) for returning an ideal encoder for a given
+         connector.  The core connector functions include a DPMS callback,
+         save/restore routines (deprecated), detection, mode probing,
+         property handling, and cleanup functions.
        </para>
 <!--!Edrivers/char/drm/drm_crtc.h-->
 <!--!Edrivers/char/drm/drm_crtc.c-->
@@ -605,22 +619,33 @@ void intel_crt_init(struct drm_device *dev)
     <title>VBlank event handling</title>
     <para>
       The DRM core exposes two vertical blank related ioctls:
-      DRM_IOCTL_WAIT_VBLANK and DRM_IOCTL_MODESET_CTL.
+      <variablelist>
+        <varlistentry>
+          <term>DRM_IOCTL_WAIT_VBLANK</term>
+          <listitem>
+            <para>
+              This takes a struct drm_wait_vblank structure as its argument,
+              and it is used to block or request a signal when a specified
+              vblank event occurs.
+            </para>
+          </listitem>
+        </varlistentry>
+        <varlistentry>
+          <term>DRM_IOCTL_MODESET_CTL</term>
+          <listitem>
+            <para>
+              This should be called by application level drivers before and
+              after mode setting, since on many devices the vertical blank
+              counter is reset at that time.  Internally, the DRM snapshots
+              the last vblank count when the ioctl is called with the
+              _DRM_PRE_MODESET command, so that the counter won't go backwards
+              (which is dealt with when _DRM_POST_MODESET is used).
+            </para>
+          </listitem>
+        </varlistentry>
+      </variablelist>
 <!--!Edrivers/char/drm/drm_irq.c-->
     </para>
-    <para>
-      DRM_IOCTL_WAIT_VBLANK takes a struct drm_wait_vblank structure
-      as its argument, and is used to block or request a signal when a
-      specified vblank event occurs.
-    </para>
-    <para>
-      DRM_IOCTL_MODESET_CTL should be called by application level
-      drivers before and after mode setting, since on many devices the
-      vertical blank counter will be reset at that time.  Internally,
-      the DRM snapshots the last vblank count when the ioctl is called
-      with the _DRM_PRE_MODESET command so that the counter won't go
-      backwards (which is dealt with when _DRM_POST_MODESET is used).
-    </para>
     <para>
       To support the functions above, the DRM core provides several
       helper functions for tracking vertical blank counters, and
@@ -632,24 +657,24 @@ void intel_crt_init(struct drm_device *dev)
       register.  The enable and disable vblank callbacks should enable
       and disable vertical blank interrupts, respectively.  In the
       absence of DRM clients waiting on vblank events, the core DRM
-      code will use the disable_vblank() function to disable
-      interrupts, which saves power.  They'll be re-enabled again when
+      code uses the disable_vblank() function to disable
+      interrupts, which saves power.  They are re-enabled again when
       a client calls the vblank wait ioctl above.
     </para>
     <para>
-      Devices that don't provide a count register can simply use an
+      A device that doesn't provide a count register may simply use an
       internal atomic counter incremented on every vertical blank
-      interrupt, and can make their enable and disable vblank
-      functions into no-ops.
+      interrupt (and then treat the enable_vblank() and disable_vblank()
+      callbacks as no-ops).
     </para>
   </sect1>
 
   <sect1>
     <title>Memory management</title>
     <para>
-      The memory manager lies at the heart of many DRM operations, and
-      is also required to support advanced client features like OpenGL
-      pbuffers.  The DRM currently contains two memory managers, TTM
+      The memory manager lies at the heart of many DRM operations; it
+      is required to support advanced client features like OpenGL
+      pbuffers.  The DRM currently contains two memory managers: TTM
       and GEM.
     </para>
 
@@ -679,41 +704,46 @@ void intel_crt_init(struct drm_device *dev)
       <para>
        GEM-enabled drivers must provide gem_init_object() and
        gem_free_object() callbacks to support the core memory
-       allocation routines.  They should also provide several driver
-       specific ioctls to support command execution, pinning, buffer
+       allocation routines.  They should also provide several driver-specific
+       ioctls to support command execution, pinning, buffer
        read &amp; write, mapping, and domain ownership transfers.
       </para>
       <para>
-       On a fundamental level, GEM involves several operations: memory
-       allocation and freeing, command execution, and aperture management
-       at command execution time.  Buffer object allocation is relatively
+       On a fundamental level, GEM involves several operations:
+       <itemizedlist>
+         <listitem>Memory allocation and freeing</listitem>
+         <listitem>Command execution</listitem>
+         <listitem>Aperture management at command execution time</listitem>
+       </itemizedlist>
+       Buffer object allocation is relatively
        straightforward and largely provided by Linux's shmem layer, which
        provides memory to back each object.  When mapped into the GTT
        or used in a command buffer, the backing pages for an object are
        flushed to memory and marked write combined so as to be coherent
-       with the GPU.  Likewise, when the GPU finishes rendering to an object,
-       if the CPU accesses it, it must be made coherent with the CPU's view
+       with the GPU.  Likewise, if the CPU accesses an object after the GPU
+       has finished rendering to the object, then the object must be made
+       coherent with the CPU's view
        of memory, usually involving GPU cache flushing of various kinds.
-       This core CPU&lt;-&gt;GPU coherency management is provided by the GEM
-       set domain function, which evaluates an object's current domain and
+       This core CPU&lt;-&gt;GPU coherency management is provided by a
+       device-specific ioctl, which evaluates an object's current domain and
        performs any necessary flushing or synchronization to put the object
        into the desired coherency domain (note that the object may be busy,
-       i.e. an active render target; in that case the set domain function
-       will block the client and wait for rendering to complete before
+       i.e. an active render target; in that case, setting the domain
+       blocks the client and waits for rendering to complete before
        performing any necessary flushing operations).
       </para>
       <para>
        Perhaps the most important GEM function is providing a command
        execution interface to clients.  Client programs construct command
-       buffers containing references to previously allocated memory objects
-       and submit them to GEM.  At that point, GEM will take care to bind
+       buffers containing references to previously allocated memory objects,
+       and then submit them to GEM.  At that point, GEM takes care to bind
        all the objects into the GTT, execute the buffer, and provide
        necessary synchronization between clients accessing the same buffers.
        This often involves evicting some objects from the GTT and re-binding
        others (a fairly expensive operation), and providing relocation
        support which hides fixed GTT offsets from clients.  Clients must
        take care not to submit command buffers that reference more objects
-       than can fit in the GTT or GEM will reject them and no rendering
+       than can fit in the GTT; otherwise, GEM will reject them and no rendering
        will occur.  Similarly, if several objects in the buffer require
        fence registers to be allocated for correct rendering (e.g. 2D blits
        on pre-965 chips), care must be taken not to require more fence
@@ -729,7 +759,7 @@ void intel_crt_init(struct drm_device *dev)
     <title>Output management</title>
     <para>
       At the core of the DRM output management code is a set of
-      structures representing CRTCs, encoders and connectors.
+      structures representing CRTCs, encoders, and connectors.
     </para>
     <para>
       A CRTC is an abstraction representing a part of the chip that
@@ -765,21 +795,19 @@ void intel_crt_init(struct drm_device *dev)
   <sect1>
     <title>Framebuffer management</title>
     <para>
-      In order to set a mode on a given CRTC, encoder and connector
-      configuration, clients need to provide a framebuffer object which
-      will provide a source of pixels for the CRTC to deliver to the encoder(s)
-      and ultimately the connector(s) in the configuration.  A framebuffer
-      is fundamentally a driver specific memory object, made into an opaque
-      handle by the DRM addfb function.  Once an fb has been created this
-      way it can be passed to the KMS mode setting routines for use in
-      a configuration.
+      Clients need to provide a framebuffer object which provides a source
+      of pixels for a CRTC to deliver to the encoder(s) and ultimately the
+      connector(s). A framebuffer is fundamentally a driver-specific memory
+      object, made into an opaque handle by the DRM's addfb() function.
+      Once a framebuffer has been created this way, it may be passed to the
+      KMS mode setting routines for use in a completed configuration.
     </para>
   </sect1>
 
   <sect1>
     <title>Command submission &amp; fencing</title>
     <para>
-      This should cover a few device specific command submission
+      This should cover a few device-specific command submission
       implementations.
     </para>
   </sect1>
@@ -789,7 +817,7 @@ void intel_crt_init(struct drm_device *dev)
     <para>
       The DRM core provides some suspend/resume code, but drivers
       wanting full suspend/resume support should provide save() and
-      restore() functions.  These will be called at suspend,
+      restore() functions.  These are called at suspend,
       hibernate, or resume time, and should perform any state save or
       restore required by your device across suspend or hibernate
       states.
@@ -812,8 +840,8 @@ void intel_crt_init(struct drm_device *dev)
     <para>
       The DRM core exports several interfaces to applications,
       generally intended to be used through corresponding libdrm
-      wrapper functions.  In addition, drivers export device specific
-      interfaces for use by userspace drivers &amp; device aware
+      wrapper functions.  In addition, drivers export device-specific
+      interfaces for use by userspace drivers &amp; device-aware
       applications through ioctls and sysfs files.
     </para>
     <para>
@@ -822,8 +850,8 @@ void intel_crt_init(struct drm_device *dev)
       management, memory management, and output management.
     </para>
     <para>
-      Cover generic ioctls and sysfs layout here.  Only need high
-      level info, since man pages will cover the rest.
+      Cover generic ioctls and sysfs layout here.  We only need high-level
+      info, since man pages should cover the rest.
     </para>
   </chapter>
 
index 54883de..ac3d001 100644 (file)
@@ -520,6 +520,11 @@ Here's a description of the fields of <varname>struct uio_mem</varname>:
 </para>
 
 <itemizedlist>
+<listitem><para>
+<varname>const char *name</varname>: Optional. Set this to help identify
+the memory region, it will show up in the corresponding sysfs node.
+</para></listitem>
+
 <listitem><para>
 <varname>int memtype</varname>: Required if the mapping is used. Set this to
 <varname>UIO_MEM_PHYS</varname> if you you have physical memory on your
@@ -553,7 +558,7 @@ instead to remember such an address.
 </itemizedlist>
 
 <para>
-Please do not touch the <varname>kobj</varname> element of
+Please do not touch the <varname>map</varname> element of
 <varname>struct uio_mem</varname>! It is used by the UIO framework
 to set up sysfs files for this mapping. Simply leave it alone.
 </para>
index 71464e0..b79d0a1 100644 (file)
@@ -98,14 +98,12 @@ You must enable "SCSI tape drive support for Smart Array 5xxx" and
 "SCSI support" in your kernel configuration to be able to use SCSI
 tape drives with your Smart Array 5xxx controller.
 
-Additionally, note that the driver will not engage the SCSI core at init 
-time.  The driver must be directed to dynamically engage the SCSI core via 
-the /proc filesystem entry which the "block" side of the driver creates as 
-/proc/driver/cciss/cciss* at runtime.  This is because at driver init time, 
-the SCSI core may not yet be initialized (because the driver is a block 
-driver) and attempting to register it with the SCSI core in such a case 
-would cause a hang.  This is best done via an initialization script 
-(typically in /etc/init.d, but could vary depending on distribution). 
+Additionally, note that the driver will engage the SCSI core at init
+time if any tape drives or medium changers are detected.  The driver may
+also be directed to dynamically engage the SCSI core via the /proc filesystem
+entry which the "block" side of the driver creates as
+/proc/driver/cciss/cciss* at runtime.  This is best done via a script.
+
 For example:
 
        for x in /proc/driver/cciss/cciss[0-9]*
index c21d777..7e62de1 100644 (file)
@@ -33,9 +33,9 @@ demonstrate this problem using nested bash shells:
 
        From a second, unrelated bash shell:
        $ kill -SIGSTOP 16690
-       $ kill -SIGCONT 16990
+       $ kill -SIGCONT 16690
 
-       <at this point 16990 exits and causes 16644 to exit too>
+       <at this point 16690 exits and causes 16644 to exit too>
 
 This happens because bash can observe both signals and choose how it
 responds to them.
index e855278..874921e 100644 (file)
@@ -33,6 +33,7 @@ qcom  Qualcomm, Inc.
 ramtron        Ramtron International
 samsung        Samsung Semiconductor
 schindler      Schindler
+sil    Silicon Image
 simtek
 sirf   SiRF Technology, Inc.
 stericsson     ST-Ericsson
index 64087c3..7671352 100644 (file)
@@ -63,8 +63,8 @@ IRC network.
 Userspace tools for creating and manipulating Btrfs file systems are
 available from the git repository at the following location:
 
- http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs-unstable.git
- git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs-unstable.git
+ http://git.kernel.org/?p=linux/kernel/git/mason/btrfs-progs.git
+ git://git.kernel.org/pub/scm/linux/kernel/git/mason/btrfs-progs.git
 
 These include the following tools:
 
index e989070..cdfe139 100644 (file)
@@ -1,22 +1,24 @@
 The I2C protocol knows about two kinds of device addresses: normal 7 bit
 addresses, and an extended set of 10 bit addresses. The sets of addresses
 do not intersect: the 7 bit address 0x10 is not the same as the 10 bit
-address 0x10 (though a single device could respond to both of them). You
-select a 10 bit address by adding an extra byte after the address
-byte:
-  S Addr7 Rd/Wr ....
-becomes
-  S 11110 Addr10 Rd/Wr
-S is the start bit, Rd/Wr the read/write bit, and if you count the number
-of bits, you will see the there are 8 after the S bit for 7 bit addresses,
-and 16 after the S bit for 10 bit addresses.
+address 0x10 (though a single device could respond to both of them).
 
-WARNING! The current 10 bit address support is EXPERIMENTAL. There are
-several places in the code that will cause SEVERE PROBLEMS with 10 bit
-addresses, even though there is some basic handling and hooks. Also,
-almost no supported adapter handles the 10 bit addresses correctly.
+I2C messages to and from 10-bit address devices have a different format.
+See the I2C specification for the details.
 
-As soon as a real 10 bit address device is spotted 'in the wild', we
-can and will add proper support. Right now, 10 bit address devices
-are defined by the I2C protocol, but we have never seen a single device
-which supports them.
+The current 10 bit address support is minimal. It should work, however
+you can expect some problems along the way:
+* Not all bus drivers support 10-bit addresses. Some don't because the
+  hardware doesn't support them (SMBus doesn't require 10-bit address
+  support for example), some don't because nobody bothered adding the
+  code (or it's there but not working properly.) Software implementation
+  (i2c-algo-bit) is known to work.
+* Some optional features do not support 10-bit addresses. This is the
+  case of automatic detection and instantiation of devices by their,
+  drivers, for example.
+* Many user-space packages (for example i2c-tools) lack support for
+  10-bit addresses.
+
+Note that 10-bit address devices are still pretty rare, so the limitations
+listed above could stay for a long time, maybe even forever if nobody
+needs them to be fixed.
index cb7f314..f049a1c 100644 (file)
@@ -20,7 +20,7 @@ ip_no_pmtu_disc - BOOLEAN
        default FALSE
 
 min_pmtu - INTEGER
-       default 562 - minimum discovered Path MTU
+       default 552 - minimum discovered Path MTU
 
 route/max_size - INTEGER
        Maximum number of routes allowed in the kernel.  Increase
index 646a89e..3139fb5 100644 (file)
@@ -123,9 +123,10 @@ please refer directly to the source code for more information about it.
 Subsystem-Level Methods
 -----------------------
 The core methods to suspend and resume devices reside in struct dev_pm_ops
-pointed to by the pm member of struct bus_type, struct device_type and
-struct class.  They are mostly of interest to the people writing infrastructure
-for buses, like PCI or USB, or device type and device class drivers.
+pointed to by the ops member of struct dev_pm_domain, or by the pm member of
+struct bus_type, struct device_type and struct class.  They are mostly of
+interest to the people writing infrastructure for platforms and buses, like PCI
+or USB, or device type and device class drivers.
 
 Bus drivers implement these methods as appropriate for the hardware and the
 drivers using it; PCI works differently from USB, and so on.  Not many people
@@ -139,41 +140,57 @@ sequencing in the driver model tree.
 
 /sys/devices/.../power/wakeup files
 -----------------------------------
-All devices in the driver model have two flags to control handling of wakeup
-events (hardware signals that can force the device and/or system out of a low
-power state).  These flags are initialized by bus or device driver code using
+All device objects in the driver model contain fields that control the handling
+of system wakeup events (hardware signals that can force the system out of a
+sleep state).  These fields are initialized by bus or device driver code using
 device_set_wakeup_capable() and device_set_wakeup_enable(), defined in
 include/linux/pm_wakeup.h.
 
-The "can_wakeup" flag just records whether the device (and its driver) can
+The "power.can_wakeup" flag just records whether the device (and its driver) can
 physically support wakeup events.  The device_set_wakeup_capable() routine
-affects this flag.  The "should_wakeup" flag controls whether the device should
-try to use its wakeup mechanism.  device_set_wakeup_enable() affects this flag;
-for the most part drivers should not change its value.  The initial value of
-should_wakeup is supposed to be false for the majority of devices; the major
-exceptions are power buttons, keyboards, and Ethernet adapters whose WoL
-(wake-on-LAN) feature has been set up with ethtool.  It should also default
-to true for devices that don't generate wakeup requests on their own but merely
-forward wakeup requests from one bus to another (like PCI bridges).
+affects this flag.  The "power.wakeup" field is a pointer to an object of type
+struct wakeup_source used for controlling whether or not the device should use
+its system wakeup mechanism and for notifying the PM core of system wakeup
+events signaled by the device.  This object is only present for wakeup-capable
+devices (i.e. devices whose "can_wakeup" flags are set) and is created (or
+removed) by device_set_wakeup_capable().
 
 Whether or not a device is capable of issuing wakeup events is a hardware
 matter, and the kernel is responsible for keeping track of it.  By contrast,
 whether or not a wakeup-capable device should issue wakeup events is a policy
 decision, and it is managed by user space through a sysfs attribute: the
-power/wakeup file.  User space can write the strings "enabled" or "disabled" to
-set or clear the "should_wakeup" flag, respectively.  This file is only present
-for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set)
-and is created (or removed) by device_set_wakeup_capable().  Reads from the
-file will return the corresponding string.
-
-The device_may_wakeup() routine returns true only if both flags are set.
+"power/wakeup" file.  User space can write the strings "enabled" or "disabled"
+to it to indicate whether or not, respectively, the device is supposed to signal
+system wakeup.  This file is only present if the "power.wakeup" object exists
+for the given device and is created (or removed) along with that object, by
+device_set_wakeup_capable().  Reads from the file will return the corresponding
+string.
+
+The "power/wakeup" file is supposed to contain the "disabled" string initially
+for the majority of devices; the major exceptions are power buttons, keyboards,
+and Ethernet adapters whose WoL (wake-on-LAN) feature has been set up with
+ethtool.  It should also default to "enabled" for devices that don't generate
+wakeup requests on their own but merely forward wakeup requests from one bus to
+another (like PCI Express ports).
+
+The device_may_wakeup() routine returns true only if the "power.wakeup" object
+exists and the corresponding "power/wakeup" file contains the string "enabled".
 This information is used by subsystems, like the PCI bus type code, to see
 whether or not to enable the devices' wakeup mechanisms.  If device wakeup
 mechanisms are enabled or disabled directly by drivers, they also should use
 device_may_wakeup() to decide what to do during a system sleep transition.
-However for runtime power management, wakeup events should be enabled whenever
-the device and driver both support them, regardless of the should_wakeup flag.
-
+Device drivers, however, are not supposed to call device_set_wakeup_enable()
+directly in any case.
+
+It ought to be noted that system wakeup is conceptually different from "remote
+wakeup" used by runtime power management, although it may be supported by the
+same physical mechanism.  Remote wakeup is a feature allowing devices in
+low-power states to trigger specific interrupts to signal conditions in which
+they should be put into the full-power state.  Those interrupts may or may not
+be used to signal system wakeup events, depending on the hardware design.  On
+some systems it is impossible to trigger them from system sleep states.  In any
+case, remote wakeup should always be enabled for runtime power management for
+all devices and drivers that support it.
 
 /sys/devices/.../power/control files
 ------------------------------------
@@ -249,20 +266,31 @@ for every device before the next phase begins.  Not all busses or classes
 support all these callbacks and not all drivers use all the callbacks.  The
 various phases always run after tasks have been frozen and before they are
 unfrozen.  Furthermore, the *_noirq phases run at a time when IRQ handlers have
-been disabled (except for those marked with the IRQ_WAKEUP flag).
-
-All phases use bus, type, or class callbacks (that is, methods defined in
-dev->bus->pm, dev->type->pm, or dev->class->pm).  These callbacks are mutually
-exclusive, so if the device type provides a struct dev_pm_ops object pointed to
-by its pm field (i.e. both dev->type and dev->type->pm are defined), the
-callbacks included in that object (i.e. dev->type->pm) will be used.  Otherwise,
-if the class provides a struct dev_pm_ops object pointed to by its pm field
-(i.e. both dev->class and dev->class->pm are defined), the PM core will use the
-callbacks from that object (i.e. dev->class->pm).  Finally, if the pm fields of
-both the device type and class objects are NULL (or those objects do not exist),
-the callbacks provided by the bus (that is, the callbacks from dev->bus->pm)
-will be used (this allows device types to override callbacks provided by bus
-types or classes if necessary).
+been disabled (except for those marked with the IRQF_NO_SUSPEND flag).
+
+All phases use PM domain, bus, type, or class callbacks (that is, methods
+defined in dev->pm_domain->ops, dev->bus->pm, dev->type->pm, or dev->class->pm).
+These callbacks are regarded by the PM core as mutually exclusive.  Moreover,
+PM domain callbacks always take precedence over bus, type and class callbacks,
+while type callbacks take precedence over bus and class callbacks, and class
+callbacks take precedence over bus callbacks.  To be precise, the following
+rules are used to determine which callback to execute in the given phase:
+
+    1. If dev->pm_domain is present, the PM core will attempt to execute the
+       callback included in dev->pm_domain->ops.  If that callback is not
+       present, no action will be carried out for the given device.
+
+    2. Otherwise, if both dev->type and dev->type->pm are present, the callback
+       included in dev->type->pm will be executed.
+
+    3. Otherwise, if both dev->class and dev->class->pm are present, the
+       callback included in dev->class->pm will be executed.
+
+    4. Otherwise, if both dev->bus and dev->bus->pm are present, the callback
+       included in dev->bus->pm will be executed.
+
+This allows PM domains and device types to override callbacks provided by bus
+types or device classes if necessary.
 
 These callbacks may in turn invoke device- or driver-specific methods stored in
 dev->driver->pm, but they don't have to.
@@ -283,9 +311,8 @@ When the system goes into the standby or memory sleep state, the phases are:
 
        After the prepare callback method returns, no new children may be
        registered below the device.  The method may also prepare the device or
-       driver in some way for the upcoming system power transition (for
-       example, by allocating additional memory required for this purpose), but
-       it should not put the device into a low-power state.
+       driver in some way for the upcoming system power transition, but it
+       should not put the device into a low-power state.
 
     2. The suspend methods should quiesce the device to stop it from performing
        I/O.  They also may save the device registers and put it into the
index 5336149..c2ae8bf 100644 (file)
@@ -44,25 +44,33 @@ struct dev_pm_ops {
 };
 
 The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks
-are executed by the PM core for either the power domain, or the device type
-(if the device power domain's struct dev_pm_ops does not exist), or the class
-(if the device power domain's and type's struct dev_pm_ops object does not
-exist), or the bus type (if the device power domain's, type's and class'
-struct dev_pm_ops objects do not exist) of the given device, so the priority
-order of callbacks from high to low is that power domain callbacks, device
-type callbacks, class callbacks and bus type callbacks, and the high priority
-one will take precedence over low priority one. The bus type, device type and
-class callbacks are referred to as subsystem-level callbacks in what follows,
-and generally speaking, the power domain callbacks are used for representing
-power domains within a SoC.
+are executed by the PM core for the device's subsystem that may be either of
+the following:
+
+  1. PM domain of the device, if the device's PM domain object, dev->pm_domain,
+     is present.
+
+  2. Device type of the device, if both dev->type and dev->type->pm are present.
+
+  3. Device class of the device, if both dev->class and dev->class->pm are
+     present.
+
+  4. Bus type of the device, if both dev->bus and dev->bus->pm are present.
+
+The PM core always checks which callback to use in the order given above, so the
+priority order of callbacks from high to low is: PM domain, device type, class
+and bus type.  Moreover, the high-priority one will always take precedence over
+a low-priority one.  The PM domain, bus type, device type and class callbacks
+are referred to as subsystem-level callbacks in what follows.
 
 By default, the callbacks are always invoked in process context with interrupts
 enabled.  However, subsystems can use the pm_runtime_irq_safe() helper function
-to tell the PM core that a device's ->runtime_suspend() and ->runtime_resume()
-callbacks should be invoked in atomic context with interrupts disabled.
-This implies that these callback routines must not block or sleep, but it also
-means that the synchronous helper functions listed at the end of Section 4 can
-be used within an interrupt handler or in an atomic context.
+to tell the PM core that their ->runtime_suspend(), ->runtime_resume() and
+->runtime_idle() callbacks may be invoked in atomic context with interrupts
+disabled for a given device.  This implies that the callback routines in
+question must not block or sleep, but it also means that the synchronous helper
+functions listed at the end of Section 4 may be used for that device within an
+interrupt handler or generally in an atomic context.
 
 The subsystem-level suspend callback is _entirely_ _responsible_ for handling
 the suspend of the device as appropriate, which may, but need not include
index 079cb3d..41c8378 100644 (file)
 
        struct serial_rs485 rs485conf;
 
-       /* Set RS485 mode: */
+       /* Enable RS485 mode: */
        rs485conf.flags |= SER_RS485_ENABLED;
 
+       /* Set logical level for RTS pin equal to 1 when sending: */
+       rs485conf.flags |= SER_RS485_RTS_ON_SEND;
+       /* or, set logical level for RTS pin equal to 0 when sending: */
+       rs485conf.flags &= ~(SER_RS485_RTS_ON_SEND);
+
+       /* Set logical level for RTS pin equal to 1 after sending: */
+       rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
+       /* or, set logical level for RTS pin equal to 0 after sending: */
+       rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
+
        /* Set rts delay before send, if needed: */
-       rs485conf.flags |= SER_RS485_RTS_BEFORE_SEND;
        rs485conf.delay_rts_before_send = ...;
 
        /* Set rts delay after send, if needed: */
-       rs485conf.flags |= SER_RS485_RTS_AFTER_SEND;
        rs485conf.delay_rts_after_send = ...;
 
        /* Set this flag if you want to receive data even whilst sending data */
diff --git a/Kbuild b/Kbuild
index 4caab4f..b8b708a 100644 (file)
--- a/Kbuild
+++ b/Kbuild
@@ -92,7 +92,7 @@ always += missing-syscalls
 targets += missing-syscalls
 
 quiet_cmd_syscalls = CALL    $<
-      cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags)
+      cmd_syscalls = $(CONFIG_SHELL) $< $(CC) $(c_flags) $(missing_syscalls_flags)
 
 missing-syscalls: scripts/checksyscalls.sh $(offsets-file) FORCE
        $(call cmd,syscalls)
index fd7e441..4475602 100644 (file)
@@ -789,6 +789,7 @@ L:  linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.pengutronix.de/git/imx/linux-2.6.git
 F:     arch/arm/mach-mx*/
+F:     arch/arm/mach-imx/
 F:     arch/arm/plat-mxc/
 
 ARM/FREESCALE IMX51
@@ -804,6 +805,13 @@ S: Maintained
 T:     git git://git.linaro.org/people/shawnguo/linux-2.6.git
 F:     arch/arm/mach-imx/*imx6*
 
+ARM/FREESCALE MXS ARM ARCHITECTURE
+M:     Shawn Guo <shawn.guo@linaro.org>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+T:     git git://git.linaro.org/people/shawnguo/linux-2.6.git
+F:     arch/arm/mach-mxs/
+
 ARM/GLOMATION GESBC9312SX MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1106,6 +1114,7 @@ F:        drivers/media/video/s5p-fimc/
 ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 M:     Kamil Debski <k.debski@samsung.com>
+M:     Jeongtae Park <jtp.park@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
 S:     Maintained
@@ -1788,6 +1797,14 @@ F:       include/net/cfg80211.h
 F:     net/wireless/*
 X:     net/wireless/wext*
 
+CHAR and MISC DRIVERS
+M:     Arnd Bergmann <arnd@arndb.de>
+M:     Greg Kroah-Hartman <greg@kroah.com>
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc.git
+S:     Maintained
+F:     drivers/char/*
+F:     drivers/misc/*
+
 CHECKPATCH
 M:     Andy Whitcroft <apw@canonical.com>
 S:     Supported
@@ -1926,9 +1943,11 @@ S:       Maintained
 F:     drivers/connector/
 
 CONTROL GROUPS (CGROUPS)
-M:     Paul Menage <paul@paulmenage.org>
+M:     Tejun Heo <tj@kernel.org>
 M:     Li Zefan <lizf@cn.fujitsu.com>
 L:     containers@lists.linux-foundation.org
+L:     cgroups@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup.git
 S:     Maintained
 F:     include/linux/cgroup*
 F:     kernel/cgroup*
@@ -2342,6 +2361,13 @@ S:       Supported
 F:     drivers/gpu/drm/i915
 F:     include/drm/i915*
 
+DRM DRIVERS FOR EXYNOS
+M:     Inki Dae <inki.dae@samsung.com>
+L:     dri-devel@lists.freedesktop.org
+S:     Supported
+F:     drivers/gpu/drm/exynos
+F:     include/drm/exynos*
+
 DSCC4 DRIVER
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
@@ -2576,7 +2602,7 @@ S:        Maintained
 F:     drivers/net/ethernet/i825xx/eexpress.*
 
 ETHERNET BRIDGE
-M:     Stephen Hemminger <shemminger@linux-foundation.org>
+M:     Stephen Hemminger <shemminger@vyatta.com>
 L:     bridge@lists.linux-foundation.org
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net:Bridge
@@ -3710,7 +3736,7 @@ F:        fs/jbd2/
 F:     include/linux/jbd2.h
 
 JSM Neo PCI based serial card
-M:     Breno Leitao <leitao@linux.vnet.ibm.com>
+M:     Lucas Tavares <lucaskt@linux.vnet.ibm.com>
 L:     linux-serial@vger.kernel.org
 S:     Maintained
 F:     drivers/tty/serial/jsm/
@@ -4296,6 +4322,7 @@ MEMORY RESOURCE CONTROLLER
 M:     Balbir Singh <bsingharora@gmail.com>
 M:     Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
 M:     KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
+L:     cgroups@vger.kernel.org
 L:     linux-mm@kvack.org
 S:     Maintained
 F:     mm/memcontrol.c
@@ -4329,7 +4356,7 @@ MIPS
 M:     Ralf Baechle <ralf@linux-mips.org>
 L:     linux-mips@linux-mips.org
 W:     http://www.linux-mips.org/
-T:     git git://git.linux-mips.org/pub/scm/linux.git
+T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
 Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
 S:     Supported
 F:     Documentation/mips/
@@ -4462,7 +4489,7 @@ S:        Supported
 F:     drivers/infiniband/hw/nes/
 
 NETEM NETWORK EMULATOR
-M:     Stephen Hemminger <shemminger@linux-foundation.org>
+M:     Stephen Hemminger <shemminger@vyatta.com>
 L:     netem@lists.linux-foundation.org
 S:     Maintained
 F:     net/sched/sch_netem.c
@@ -4939,7 +4966,7 @@ F:        drivers/char/ppdev.c
 F:     include/linux/ppdev.h
 
 PARAVIRT_OPS INTERFACE
-M:     Jeremy Fitzhardinge <jeremy@xensource.com>
+M:     Jeremy Fitzhardinge <jeremy@goop.org>
 M:     Chris Wright <chrisw@sous-sol.org>
 M:     Alok Kataria <akataria@vmware.com>
 M:     Rusty Russell <rusty@rustcorp.com.au>
@@ -5976,7 +6003,7 @@ S:        Maintained
 F:     drivers/usb/misc/sisusbvga/
 
 SKGE, SKY2 10/100/1000 GIGABIT ETHERNET DRIVERS
-M:     Stephen Hemminger <shemminger@linux-foundation.org>
+M:     Stephen Hemminger <shemminger@vyatta.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/marvell/sk*
@@ -7390,8 +7417,8 @@ S:        Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
 
 XEN HYPERVISOR INTERFACE
-M:     Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
 M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+M:     Jeremy Fitzhardinge <jeremy@goop.org>
 L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
 L:     virtualization@lists.linux-foundation.org
 S:     Supported
@@ -7424,7 +7451,8 @@ F:        drivers/xen/*swiotlb*
 
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
-M:     Alex Elder <aelder@sgi.com>
+M:     Ben Myers <bpm@sgi.com>
+M:     Alex Elder <elder@kernel.org>
 M:     xfs-masters@oss.sgi.com
 L:     xfs@oss.sgi.com
 W:     http://oss.sgi.com/projects/xfs
index 361e4f0..12aafc2 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 2
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc4
 NAME = Saber-toothed Squirrel
 
 # *DOCUMENTATION*
index 44789ef..e084b7e 100644 (file)
@@ -1231,7 +1231,7 @@ config ARM_ERRATA_742231
          capabilities of the processor.
 
 config PL310_ERRATA_588369
-       bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
+       bool "PL310 errata: Clean & Invalidate maintenance operations do not invalidate clean lines"
        depends on CACHE_L2X0
        help
           The PL310 L2 cache controller implements three types of Clean &
@@ -1256,7 +1256,7 @@ config ARM_ERRATA_720789
          entries regardless of the ASID.
 
 config PL310_ERRATA_727915
-       bool "Background Clean & Invalidate by Way operation can cause data corruption"
+       bool "PL310 errata: Background Clean & Invalidate by Way operation can cause data corruption"
        depends on CACHE_L2X0
        help
          PL310 implements the Clean & Invalidate by Way L2 cache maintenance
@@ -1289,8 +1289,8 @@ config ARM_ERRATA_751472
          operation is received by a CPU before the ICIALLUIS has completed,
          potentially leading to corrupted entries in the cache or TLB.
 
-config ARM_ERRATA_753970
-       bool "ARM errata: cache sync operation may be faulty"
+config PL310_ERRATA_753970
+       bool "PL310 errata: cache sync operation may be faulty"
        depends on CACHE_PL310
        help
          This option enables the workaround for the 753970 PL310 (r3p0) erratum.
@@ -1352,6 +1352,18 @@ config ARM_ERRATA_764369
          relevant cache maintenance functions and sets a specific bit
          in the diagnostic control register of the SCU.
 
+config PL310_ERRATA_769419
+       bool "PL310 errata: no automatic Store Buffer drain"
+       depends on CACHE_L2X0
+       help
+         On revisions of the PL310 prior to r3p2, the Store Buffer does
+         not automatically drain. This can cause normal, non-cacheable
+         writes to be retained when the memory system is idle, leading
+         to suboptimal I/O performance for drivers using coherent DMA.
+         This option adds a write barrier to the cpu_idle loop so that,
+         on systems with an outer cache, the store buffer is drained
+         explicitly.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
index 176062a..5df26a9 100644 (file)
@@ -65,6 +65,8 @@ $(obj)/%.dtb: $(src)/dts/%.dts
 
 $(obj)/dtbs: $(addprefix $(obj)/, $(dtb-y))
 
+clean-files := *.dtb
+
 quiet_cmd_uimage = UIMAGE  $@
       cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A arm -O linux -T kernel \
                   -C none -a $(LOADADDR) -e $(STARTADDR) \
index 9b29a62..3f9abd6 100644 (file)
        sdhci@c8000400 {
                cd-gpios = <&gpio 69 0>; /* gpio PI5 */
                wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-               power-gpios = <&gpio 155 0>; /* gpio PT3 */
+               power-gpios = <&gpio 70 0>; /* gpio PI6 */
        };
 
        sdhci@c8000600 {
-               power-gpios = <&gpio 70 0>; /* gpio PI6 */
                support-8bit;
        };
 };
index 0e6ae47..410a546 100644 (file)
@@ -526,7 +526,8 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
                sizeof(u32));
        BUG_ON(!gic->saved_ppi_conf);
 
-       cpu_pm_register_notifier(&gic_notifier_block);
+       if (gic == &gic_data[0])
+               cpu_pm_register_notifier(&gic_notifier_block);
 }
 #else
 static void __init gic_pm_init(struct gic_chip_data *gic)
@@ -581,13 +582,16 @@ void __init gic_init(unsigned int gic_nr, int irq_start,
         * For primary GICs, skip over SGIs.
         * For secondary GICs, skip over PPIs, too.
         */
+       domain->hwirq_base = 32;
        if (gic_nr == 0) {
                gic_cpu_base_addr = cpu_base;
-               domain->hwirq_base = 16;
-               if (irq_start > 0)
-                       irq_start = (irq_start & ~31) + 16;
-       } else
-               domain->hwirq_base = 32;
+
+               if ((irq_start & 31) > 0) {
+                       domain->hwirq_base = 16;
+                       if (irq_start != -1)
+                               irq_start = (irq_start & ~31) + 16;
+               }
+       }
 
        /*
         * Find out how many interrupts are supported.
index 7129cfb..f407a6b 100644 (file)
@@ -1211,8 +1211,8 @@ static inline u32 _prepare_ccr(const struct pl330_reqcfg *rqc)
        ccr |= (rqc->brst_size << CC_SRCBRSTSIZE_SHFT);
        ccr |= (rqc->brst_size << CC_DSTBRSTSIZE_SHFT);
 
-       ccr |= (rqc->dcctl << CC_SRCCCTRL_SHFT);
-       ccr |= (rqc->scctl << CC_DSTCCTRL_SHFT);
+       ccr |= (rqc->scctl << CC_SRCCCTRL_SHFT);
+       ccr |= (rqc->dcctl << CC_DSTCCTRL_SHFT);
 
        ccr |= (rqc->swap << CC_SWAP_SHFT);
 
@@ -1623,6 +1623,11 @@ static inline int _alloc_event(struct pl330_thread *thrd)
        return -1;
 }
 
+static bool _chan_ns(const struct pl330_info *pi, int i)
+{
+       return pi->pcfg.irq_ns & (1 << i);
+}
+
 /* Upon success, returns IdentityToken for the
  * allocated channel, NULL otherwise.
  */
@@ -1647,7 +1652,8 @@ void *pl330_request_channel(const struct pl330_info *pi)
 
        for (i = 0; i < chans; i++) {
                thrd = &pl330->channels[i];
-               if (thrd->free) {
+               if ((thrd->free) && (!_manager_ns(thrd) ||
+                                       _chan_ns(pi, i))) {
                        thrd->ev = _alloc_event(thrd);
                        if (thrd->ev >= 0) {
                                thrd->free = false;
diff --git a/arch/arm/configs/at91cap9_defconfig b/arch/arm/configs/at91cap9_defconfig
new file mode 100644 (file)
index 0000000..8826eb2
--- /dev/null
@@ -0,0 +1,108 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91CAP9=y
+CONFIG_MACH_AT91CAP9ADK=y
+CONFIG_MTD_AT91_DATAFLASH_CARD=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ADS7846=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
diff --git a/arch/arm/configs/at91cap9adk_defconfig b/arch/arm/configs/at91cap9adk_defconfig
deleted file mode 100644 (file)
index ffb1edd..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91CAP9=y
-CONFIG_MACH_AT91CAP9ADK=y
-CONFIG_MTD_AT91_DATAFLASH_CARD=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=ttyS0,115200 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_JEDECPROBE=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ADS7846=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_HW_RANDOM=y
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ETH=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
index 38cb7c9..bbe4e1a 100644 (file)
@@ -5,7 +5,6 @@ CONFIG_SYSVIPC=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_MODULES=y
 CONFIG_MODULE_FORCE_LOAD=y
@@ -56,7 +55,6 @@ CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_NET_IPIP=m
-CONFIG_NET_IPGRE=m
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
@@ -75,18 +73,8 @@ CONFIG_IPV6_TUNNEL=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
 CONFIG_BT=m
-CONFIG_BT_L2CAP=m
-CONFIG_BT_SCO=m
-CONFIG_BT_RFCOMM=m
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=m
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_AFS_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -108,8 +96,6 @@ CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_TCLIB=y
-CONFIG_EEPROM_LEGACY=m
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_BLK_DEV_SR=m
@@ -119,14 +105,23 @@ CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_TUN=m
+CONFIG_ARM_AT91_ETHER=y
 CONFIG_PHYLIB=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_SMSC_PHY=y
 CONFIG_MICREL_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_ARM_AT91_ETHER=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MPPE=m
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=y
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
 CONFIG_USB_CATC=m
 CONFIG_USB_KAWETH=m
 CONFIG_USB_PEGASUS=m
@@ -139,18 +134,6 @@ CONFIG_USB_NET_RNDIS_HOST=m
 CONFIG_USB_ALI_M5632=y
 CONFIG_USB_AN2720=y
 CONFIG_USB_EPSON2888=y
-CONFIG_PPP=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPP_FILTER=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_BSDCOMP=y
-CONFIG_PPP_MPPE=m
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-CONFIG_SLIP_MODE_SLIP6=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
@@ -158,9 +141,9 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_LEGACY_PTY_COUNT=32
 CONFIG_SERIAL_ATMEL=y
 CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=32
 CONFIG_HW_RANDOM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -290,7 +273,6 @@ CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_SMB_FS=m
 CONFIG_CIFS=m
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_MAC_PARTITION=y
@@ -335,7 +317,6 @@ CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_FTRACE is not set
 CONFIG_CRYPTO_PCBC=y
 CONFIG_CRYPTO_SHA1=y
diff --git a/arch/arm/configs/at91sam9260_defconfig b/arch/arm/configs/at91sam9260_defconfig
new file mode 100644 (file)
index 0000000..505b376
--- /dev/null
@@ -0,0 +1,91 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9260=y
+CONFIG_ARCH_AT91SAM9260_SAM9XE=y
+CONFIG_MACH_AT91SAM9260EK=y
+CONFIG_MACH_CAM60=y
+CONFIG_MACH_SAM9_L9260=y
+CONFIG_MACH_AFEB9260=y
+CONFIG_MACH_USB_A9260=y
+CONFIG_MACH_QIL_A9260=y
+CONFIG_MACH_CPU9260=y
+CONFIG_MACH_FLEXIBITY=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+# CONFIG_USB_HID is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
deleted file mode 100644 (file)
index f8a9226..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9260=y
-CONFIG_MACH_AT91SAM9260EK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_USB_HID is not set
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91sam9g20_defconfig b/arch/arm/configs/at91sam9g20_defconfig
new file mode 100644 (file)
index 0000000..9123568
--- /dev/null
@@ -0,0 +1,124 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9G20=y
+CONFIG_MACH_AT91SAM9G20EK=y
+CONFIG_MACH_AT91SAM9G20EK_2MMC=y
+CONFIG_MACH_CPU9G20=y
+CONFIG_MACH_ACMENETUSFOXG20=y
+CONFIG_MACH_PORTUXG20=y
+CONFIG_MACH_STAMP9G20=y
+CONFIG_MACH_PCONTROL_G20=y
+CONFIG_MACH_GSIA18S=y
+CONFIG_MACH_USB_A9G20=y
+CONFIG_MACH_SNAPPER_9260=y
+CONFIG_MACH_AT91SAM_DT=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_AEABI=y
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_MACB=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_SPIDEV=y
+# CONFIG_HWMON is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SEQUENCER=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_SEQUENCER_OSS=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
diff --git a/arch/arm/configs/at91sam9g20ek_defconfig b/arch/arm/configs/at91sam9g20ek_defconfig
deleted file mode 100644 (file)
index 9e90e6d..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9G20=y
-CONFIG_MACH_AT91SAM9G20EK=y
-CONFIG_MACH_AT91SAM9G20EK_2MMC=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_AEABI=y
-CONFIG_LEDS=y
-CONFIG_LEDS_CPU=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,3145728 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_LOWLEVEL is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_KEYBOARD_ATKBD is not set
-CONFIG_KEYBOARD_GPIO=y
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
-CONFIG_HW_RANDOM=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-CONFIG_SPI_SPIDEV=y
-# CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_SEQUENCER=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_SND_SEQUENCER_OSS=y
-# CONFIG_SND_VERBOSE_PROCFS is not set
-CONFIG_SND_AT73C213=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-# CONFIG_USB_DEVICE_CLASS is not set
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=m
-CONFIG_USB_GADGETFS=m
-CONFIG_USB_FILE_STORAGE=m
-CONFIG_USB_G_SERIAL=m
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=y
-CONFIG_LEDS_GPIO=y
-CONFIG_LEDS_TRIGGERS=y
-CONFIG_LEDS_TRIGGER_TIMER=y
-CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_SUMMARY=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
index c5876d2..606d48f 100644 (file)
@@ -18,6 +18,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_AT91=y
 CONFIG_ARCH_AT91SAM9G45=y
 CONFIG_MACH_AT91SAM9M10G45EK=y
+CONFIG_MACH_AT91SAM_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 CONFIG_AT91_SLOW_CLOCK=y
 CONFIG_AEABI=y
@@ -73,11 +74,8 @@ CONFIG_SCSI_MULTI_LUN=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
 CONFIG_MII=y
-CONFIG_DAVICOM_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_MACB=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_DAVICOM_PHY=y
 CONFIG_LIBERTAS_THINFIRM=m
 CONFIG_LIBERTAS_THINFIRM_USB=m
 CONFIG_AT76C50X_USB=m
@@ -131,7 +129,6 @@ CONFIG_I2C_GPIO=y
 CONFIG_SPI=y
 CONFIG_SPI_ATMEL=y
 # CONFIG_HWMON is not set
-# CONFIG_MFD_SUPPORT is not set
 CONFIG_FB=y
 CONFIG_FB_ATMEL=y
 CONFIG_FB_UDL=m
diff --git a/arch/arm/configs/at91sam9rl_defconfig b/arch/arm/configs/at91sam9rl_defconfig
new file mode 100644 (file)
index 0000000..ad562ee
--- /dev/null
@@ -0,0 +1,79 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91SAM9RL=y
+CONFIG_MACH_AT91SAM9RLEK=y
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+# CONFIG_ARM_THUMB is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
+CONFIG_FPE_NWFPE=y
+CONFIG_NET=y
+CONFIG_UNIX=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_DATAFLASH=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=4
+CONFIG_BLK_DEV_RAM_SIZE=24576
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
+# CONFIG_SERIO is not set
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_GPIO=y
+CONFIG_SPI=y
+CONFIG_SPI_ATMEL=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_AT91SAM9X_WATCHDOG=y
+CONFIG_FB=y
+CONFIG_FB_ATMEL=y
+CONFIG_MMC=y
+CONFIG_MMC_AT91=m
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AT91SAM9=y
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_15=y
+CONFIG_NLS_UTF8=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
diff --git a/arch/arm/configs/at91sam9rlek_defconfig b/arch/arm/configs/at91sam9rlek_defconfig
deleted file mode 100644 (file)
index 75621e4..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_LOCALVERSION_AUTO is not set
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_SLAB=y
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_ARCH_AT91=y
-CONFIG_ARCH_AT91SAM9RL=y
-CONFIG_MACH_AT91SAM9RLEK=y
-CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
-# CONFIG_ARM_THUMB is not set
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="mem=64M console=ttyS0,115200 initrd=0x21100000,17105363 root=/dev/ram0 rw"
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_UNIX=y
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_DATAFLASH=y
-CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ATMEL=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=4
-CONFIG_BLK_DEV_RAM_SIZE=24576
-CONFIG_ATMEL_SSC=y
-CONFIG_SCSI=y
-CONFIG_BLK_DEV_SD=y
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=320
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=240
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_ATMEL=y
-CONFIG_SERIAL_ATMEL_CONSOLE=y
-# CONFIG_HW_RANDOM is not set
-CONFIG_I2C=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_GPIO=y
-CONFIG_SPI=y
-CONFIG_SPI_ATMEL=y
-# CONFIG_HWMON is not set
-CONFIG_WATCHDOG=y
-CONFIG_WATCHDOG_NOWAYOUT=y
-CONFIG_AT91SAM9X_WATCHDOG=y
-CONFIG_FB=y
-CONFIG_FB_ATMEL=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_MMC=y
-CONFIG_MMC_AT91=m
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_AT91SAM9=y
-CONFIG_EXT2_FS=y
-CONFIG_INOTIFY=y
-CONFIG_MSDOS_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_CRAMFS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_CODEPAGE_850=y
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NLS_UTF8=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
index 227a477..d95763d 100644 (file)
@@ -287,7 +287,7 @@ CONFIG_USB=y
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
index 176ec22..fd996bb 100644 (file)
@@ -263,7 +263,7 @@ CONFIG_USB=y
 # CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_MMC=y
index a88e64d..443675d 100644 (file)
@@ -132,7 +132,7 @@ CONFIG_USB_MON=m
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 # CONFIG_USB_ETH_RNDIS is not set
 CONFIG_USB_GADGETFS=m
index 7b63462..a7e7775 100644 (file)
@@ -48,7 +48,6 @@ CONFIG_MACH_SX1=y
 CONFIG_MACH_NOKIA770=y
 CONFIG_MACH_AMS_DELTA=y
 CONFIG_MACH_OMAP_GENERIC=y
-CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER=y
 CONFIG_OMAP_ARM_216MHZ=y
 CONFIG_OMAP_ARM_195MHZ=y
 CONFIG_OMAP_ARM_192MHZ=y
index 4a5a126..374000e 100644 (file)
@@ -14,8 +14,6 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_U300=y
 CONFIG_MACH_U300=y
 CONFIG_MACH_U300_BS335=y
-CONFIG_MACH_U300_DUAL_RAM=y
-CONFIG_U300_DEBUG=y
 CONFIG_MACH_U300_SPIDUMMY=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -26,19 +24,21 @@ CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CMDLINE="root=/dev/ram0 rw rootfstype=rootfs console=ttyAMA0,115200n8 lpj=515072"
 CONFIG_CPU_IDLE=y
 CONFIG_FPE_NWFPE=y
-CONFIG_PM=y
 # CONFIG_SUSPEND is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
-# CONFIG_MISC_DEVICES is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSMC=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_INPUT_MOUSE is not set
 # CONFIG_SERIO is not set
+CONFIG_LEGACY_PTY_COUNT=16
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_LEGACY_PTY_COUNT=16
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_HWMON is not set
@@ -51,6 +51,7 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
 CONFIG_MMC=y
+CONFIG_MMC_CLKGATE=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_HCTOSYS is not set
@@ -65,10 +66,8 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 # CONFIG_CRC32 is not set
index 97d31a4..2d7b6e7 100644 (file)
@@ -10,7 +10,7 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_ARCH_U8500=y
 CONFIG_UX500_SOC_DB5500=y
 CONFIG_UX500_SOC_DB8500=y
-CONFIG_MACH_U8500=y
+CONFIG_MACH_HREFV60=y
 CONFIG_MACH_SNOWBALL=y
 CONFIG_MACH_U5500=y
 CONFIG_NO_HZ=y
@@ -24,6 +24,7 @@ CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_PM_RUNTIME=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
@@ -41,11 +42,8 @@ CONFIG_MISC_DEVICES=y
 CONFIG_AB8500_PWM=y
 CONFIG_SENSORS_BH1780=y
 CONFIG_NETDEVICES=y
-CONFIG_SMSC_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_SMSC911X=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_SMSC_PHY=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
@@ -72,15 +70,12 @@ CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_STMPE=y
 CONFIG_GPIO_TC3589X=y
-# CONFIG_HWMON is not set
 CONFIG_MFD_STMPE=y
 CONFIG_MFD_TC3589X=y
+CONFIG_AB5500_CORE=y
 CONFIG_AB8500_CORE=y
 CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
-CONFIG_USB_MUSB_HDRC=y
-CONFIG_USB_GADGET_MUSB_HDRC=y
-CONFIG_MUSB_PIO_ONLY=y
 CONFIG_USB_GADGET=y
 CONFIG_AB8500_USB=y
 CONFIG_MMC=y
@@ -97,6 +92,7 @@ CONFIG_DMADEVICES=y
 CONFIG_STE_DMA40=y
 CONFIG_STAGING=y
 CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
+CONFIG_HSEM_U8500=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
index 59577ad..547a3c1 100644 (file)
@@ -140,7 +140,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_MCT_U232=m
 CONFIG_USB_GADGET=m
-CONFIG_USB_GADGET_PXA27X=y
+CONFIG_USB_PXA27X=y
 CONFIG_USB_ETH=m
 CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
index 1db1143..7df239b 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef __ASM_ARM_HARDWARE_L2X0_H
 #define __ASM_ARM_HARDWARE_L2X0_H
 
+#include <linux/errno.h>
+
 #define L2X0_CACHE_ID                  0x000
 #define L2X0_CACHE_TYPE                        0x004
 #define L2X0_CTRL                      0x100
index 7d19425..2b0efc3 100644 (file)
@@ -13,6 +13,7 @@
 struct tag;
 struct meminfo;
 struct sys_timer;
+struct pt_regs;
 
 struct machine_desc {
        unsigned int            nr;             /* architecture number  */
index 71d99b8..0bda22c 100644 (file)
@@ -55,16 +55,6 @@ reserve_pmu(enum arm_pmu_type type);
 extern void
 release_pmu(enum arm_pmu_type type);
 
-/**
- * init_pmu() - Initialise the PMU.
- *
- * Initialise the system ready for PMU enabling. This should typically set the
- * IRQ affinity and nothing else. The users (oprofile/perf events etc) will do
- * the actual hardware initialisation.
- */
-extern int
-init_pmu(enum arm_pmu_type type);
-
 #else /* CONFIG_CPU_HAS_PMU */
 
 #include <linux/err.h>
index a7e457e..58b8b84 100644 (file)
@@ -25,7 +25,7 @@ extern struct cputopo_arm cpu_topology[NR_CPUS];
 
 void init_cpu_topology(void);
 void store_cpu_topology(unsigned int cpuid);
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu);
+const struct cpumask *cpu_coregroup_mask(int cpu);
 
 #else
 
index c60a294..4a11237 100644 (file)
 #define __NR_syncfs                    (__NR_SYSCALL_BASE+373)
 #define __NR_sendmmsg                  (__NR_SYSCALL_BASE+374)
 #define __NR_setns                     (__NR_SYSCALL_BASE+375)
+#define __NR_process_vm_readv          (__NR_SYSCALL_BASE+376)
+#define __NR_process_vm_writev         (__NR_SYSCALL_BASE+377)
 
 /*
  * The following SWIs are ARM private.
index 9943e9e..463ff4a 100644 (file)
                CALL(sys_syncfs)
                CALL(sys_sendmmsg)
 /* 375 */      CALL(sys_setns)
+               CALL(sys_process_vm_readv)
+               CALL(sys_process_vm_writev)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index 9ad50c4..b145f16 100644 (file)
@@ -497,7 +497,7 @@ ENDPROC(__und_usr)
        .popsection
        .pushsection __ex_table,"a"
        .long   1b, 4b
-#if __LINUX_ARM_ARCH__ >= 7
+#if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
        .long   2b, 4b
        .long   3b, 4b
 #endif
index 566c54c..08c82fd 100644 (file)
@@ -360,7 +360,7 @@ __secondary_data:
  *  r13 = *virtual* address to jump to upon completion
  */
 __enable_mmu:
-#ifdef CONFIG_ALIGNMENT_TRAP
+#if defined(CONFIG_ALIGNMENT_TRAP) && __LINUX_ARM_ARCH__ < 6
        orr     r0, r0, #CR_A
 #else
        bic     r0, r0, #CR_A
index 9fe8910..8a30c89 100644 (file)
@@ -519,10 +519,12 @@ static const union decode_item arm_cccc_0000_____1001_table[] = {
 static const union decode_item arm_cccc_0001_____1001_table[] = {
        /* Synchronization primitives                                   */
 
+#if __LINUX_ARM_ARCH__ < 6
+       /* Deprecated on ARMv6 and may be UNDEFINED on v7               */
        /* SMP/SWPB             cccc 0001 0x00 xxxx xxxx xxxx 1001 xxxx */
        DECODE_EMULATEX (0x0fb000f0, 0x01000090, emulate_rd12rn16rm0_rwflags_nopc,
                                                 REGS(NOPC, NOPC, 0, 0, NOPC)),
-
+#endif
        /* LDREX/STREX{,D,B,H}  cccc 0001 1xxx xxxx xxxx xxxx 1001 xxxx */
        /* And unallocated instructions...                              */
        DECODE_END
index fc82de8..ba32b39 100644 (file)
@@ -427,18 +427,25 @@ void kprobe_arm_test_cases(void)
 
        TEST_GROUP("Synchronization primitives")
 
-       /*
-        * Use hard coded constants for SWP instructions to avoid warnings
-        * about deprecated instructions.
-        */
-       TEST_RP( ".word 0xe108e097 @ swp        lr, r",7,VAL2,", [r",8,0,"]")
-       TEST_R(  ".word 0x610d0091 @ swpvs      r0, r",1,VAL1,", [sp]")
-       TEST_RP( ".word 0xe10cd09e @ swp        sp, r",14,VAL2,", [r",12,13*4,"]")
+#if __LINUX_ARM_ARCH__ < 6
+       TEST_RP("swp    lr, r",7,VAL2,", [r",8,0,"]")
+       TEST_R( "swpvs  r0, r",1,VAL1,", [sp]")
+       TEST_RP("swp    sp, r",14,VAL2,", [r",12,13*4,"]")
+#else
+       TEST_UNSUPPORTED(".word 0xe108e097 @ swp        lr, r7, [r8]")
+       TEST_UNSUPPORTED(".word 0x610d0091 @ swpvs      r0, r1, [sp]")
+       TEST_UNSUPPORTED(".word 0xe10cd09e @ swp        sp, r14 [r12]")
+#endif
        TEST_UNSUPPORTED(".word 0xe102f091 @ swp pc, r1, [r2]")
        TEST_UNSUPPORTED(".word 0xe102009f @ swp r0, pc, [r2]")
        TEST_UNSUPPORTED(".word 0xe10f0091 @ swp r0, r1, [pc]")
-       TEST_RP( ".word 0xe148e097 @ swpb       lr, r",7,VAL2,", [r",8,0,"]")
-       TEST_R(  ".word 0x614d0091 @ swpvsb     r0, r",1,VAL1,", [sp]")
+#if __LINUX_ARM_ARCH__ < 6
+       TEST_RP("swpb   lr, r",7,VAL2,", [r",8,0,"]")
+       TEST_R( "swpvsb r0, r",1,VAL1,", [sp]")
+#else
+       TEST_UNSUPPORTED(".word 0xe148e097 @ swpb       lr, r7, [r8]")
+       TEST_UNSUPPORTED(".word 0x614d0091 @ swpvsb     r0, r1, [sp]")
+#endif
        TEST_UNSUPPORTED(".word 0xe142f091 @ swpb pc, r1, [r2]")
 
        TEST_UNSUPPORTED(".word 0xe1100090") /* Unallocated space */
@@ -550,7 +557,7 @@ void kprobe_arm_test_cases(void)
        TEST_RPR(  "strccd      r",8, VAL2,", [r",13,0, ", r",12,48,"]")
        TEST_RPR(  "strd        r",4, VAL1,", [r",2, 24,", r",3, 48,"]!")
        TEST_RPR(  "strcsd      r",12,VAL2,", [r",11,48,", -r",10,24,"]!")
-       TEST_RPR(  "strd        r",2, VAL1,", [r",3, 24,"], r",4,48,"")
+       TEST_RPR(  "strd        r",2, VAL1,", [r",5, 24,"], r",4,48,"")
        TEST_RPR(  "strd        r",10,VAL2,", [r",9, 48,"], -r",7,24,"")
        TEST_UNSUPPORTED(".word 0xe1afc0fa      @ strd r12, [pc, r10]!")
 
index 5e726c3..5d8b857 100644 (file)
@@ -222,8 +222,8 @@ void kprobe_thumb16_test_cases(void)
 DONT_TEST_IN_ITBLOCK(
        TEST_BF_R(  "cbnz       r",0,0, ", 2f")
        TEST_BF_R(  "cbz        r",2,-1,", 2f")
-       TEST_BF_RX( "cbnz       r",4,1, ", 2f",0x20)
-       TEST_BF_RX( "cbz        r",7,0, ", 2f",0x40)
+       TEST_BF_RX( "cbnz       r",4,1, ", 2f", SPACE_0x20)
+       TEST_BF_RX( "cbz        r",7,0, ", 2f", SPACE_0x40)
 )
        TEST_R("sxth    r0, r",7, HH1,"")
        TEST_R("sxth    r7, r",0, HH2,"")
@@ -246,7 +246,7 @@ DONT_TEST_IN_ITBLOCK(
        TESTCASE_START(code)            \
        TEST_ARG_PTR(13, offset)        \
        TEST_ARG_END("")                \
-       TEST_BRANCH_F(code,0)           \
+       TEST_BRANCH_F(code)             \
        TESTCASE_END
 
        TEST("push      {r0}")
@@ -319,8 +319,8 @@ CONDITION_INSTRUCTIONS(8,
 
        TEST_BF(  "b    2f")
        TEST_BB(  "b    2b")
-       TEST_BF_X("b    2f", 0x400)
-       TEST_BB_X("b    2b", 0x400)
+       TEST_BF_X("b    2f", SPACE_0x400)
+       TEST_BB_X("b    2b", SPACE_0x400)
 
        TEST_GROUP("Testing instructions in IT blocks")
 
@@ -746,7 +746,7 @@ CONDITION_INSTRUCTIONS(22,
        TEST_BB("bne.w  2b")
        TEST_BF("bgt.w  2f")
        TEST_BB("blt.w  2b")
-       TEST_BF_X("bpl.w        2f",0x1000)
+       TEST_BF_X("bpl.w        2f", SPACE_0x1000)
 )
 
        TEST_UNSUPPORTED("msr   cpsr, r0")
@@ -786,11 +786,11 @@ CONDITION_INSTRUCTIONS(22,
 
        TEST_BF(  "b.w  2f")
        TEST_BB(  "b.w  2b")
-       TEST_BF_X("b.w  2f", 0x1000)
+       TEST_BF_X("b.w  2f", SPACE_0x1000)
 
        TEST_BF(  "bl.w 2f")
        TEST_BB(  "bl.w 2b")
-       TEST_BB_X("bl.w 2b", 0x1000)
+       TEST_BB_X("bl.w 2b", SPACE_0x1000)
 
        TEST_X( "blx    __dummy_arm_subroutine",
                ".arm                           \n\t"
index 0dc5d77..e28a869 100644 (file)
@@ -149,23 +149,31 @@ struct test_arg_end {
        "1:     "instruction"                           \n\t"   \
        "       nop                                     \n\t"
 
-#define TEST_BRANCH_F(instruction, xtra_dist)                  \
+#define TEST_BRANCH_F(instruction)                             \
        TEST_INSTRUCTION(instruction)                           \
-       ".if "#xtra_dist"                               \n\t"   \
        "       b       99f                             \n\t"   \
-       ".space "#xtra_dist"                            \n\t"   \
-       ".endif                                         \n\t"   \
+       "2:     nop                                     \n\t"
+
+#define TEST_BRANCH_B(instruction)                             \
+       "       b       50f                             \n\t"   \
+       "       b       99f                             \n\t"   \
+       "2:     nop                                     \n\t"   \
+       "       b       99f                             \n\t"   \
+       TEST_INSTRUCTION(instruction)
+
+#define TEST_BRANCH_FX(instruction, codex)                     \
+       TEST_INSTRUCTION(instruction)                           \
+       "       b       99f                             \n\t"   \
+       codex"                                          \n\t"   \
        "       b       99f                             \n\t"   \
        "2:     nop                                     \n\t"
 
-#define TEST_BRANCH_B(instruction, xtra_dist)                  \
+#define TEST_BRANCH_BX(instruction, codex)                     \
        "       b       50f                             \n\t"   \
        "       b       99f                             \n\t"   \
        "2:     nop                                     \n\t"   \
        "       b       99f                             \n\t"   \
-       ".if "#xtra_dist"                               \n\t"   \
-       ".space "#xtra_dist"                            \n\t"   \
-       ".endif                                         \n\t"   \
+       codex"                                          \n\t"   \
        TEST_INSTRUCTION(instruction)
 
 #define TESTCASE_END                                           \
@@ -301,47 +309,60 @@ struct test_arg_end {
        TESTCASE_START(code1 #reg1 code2)       \
        TEST_ARG_PTR(reg1, val1)                \
        TEST_ARG_END("")                        \
-       TEST_BRANCH_F(code1 #reg1 code2, 0)     \
+       TEST_BRANCH_F(code1 #reg1 code2)        \
        TESTCASE_END
 
-#define TEST_BF_X(code, xtra_dist)             \
+#define TEST_BF(code)                          \
        TESTCASE_START(code)                    \
        TEST_ARG_END("")                        \
-       TEST_BRANCH_F(code, xtra_dist)          \
+       TEST_BRANCH_F(code)                     \
        TESTCASE_END
 
-#define TEST_BB_X(code, xtra_dist)             \
+#define TEST_BB(code)                          \
        TESTCASE_START(code)                    \
        TEST_ARG_END("")                        \
-       TEST_BRANCH_B(code, xtra_dist)          \
+       TEST_BRANCH_B(code)                     \
        TESTCASE_END
 
-#define TEST_BF_RX(code1, reg, val, code2, xtra_dist)  \
-       TESTCASE_START(code1 #reg code2)                \
-       TEST_ARG_REG(reg, val)                          \
-       TEST_ARG_END("")                                \
-       TEST_BRANCH_F(code1 #reg code2, xtra_dist)      \
+#define TEST_BF_R(code1, reg, val, code2)      \
+       TESTCASE_START(code1 #reg code2)        \
+       TEST_ARG_REG(reg, val)                  \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_F(code1 #reg code2)         \
        TESTCASE_END
 
-#define TEST_BB_RX(code1, reg, val, code2, xtra_dist)  \
-       TESTCASE_START(code1 #reg code2)                \
-       TEST_ARG_REG(reg, val)                          \
-       TEST_ARG_END("")                                \
-       TEST_BRANCH_B(code1 #reg code2, xtra_dist)      \
+#define TEST_BB_R(code1, reg, val, code2)      \
+       TESTCASE_START(code1 #reg code2)        \
+       TEST_ARG_REG(reg, val)                  \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_B(code1 #reg code2)         \
        TESTCASE_END
 
-#define TEST_BF(code)  TEST_BF_X(code, 0)
-#define TEST_BB(code)  TEST_BB_X(code, 0)
-
-#define TEST_BF_R(code1, reg, val, code2) TEST_BF_RX(code1, reg, val, code2, 0)
-#define TEST_BB_R(code1, reg, val, code2) TEST_BB_RX(code1, reg, val, code2, 0)
-
 #define TEST_BF_RR(code1, reg1, val1, code2, reg2, val2, code3)        \
        TESTCASE_START(code1 #reg1 code2 #reg2 code3)           \
        TEST_ARG_REG(reg1, val1)                                \
        TEST_ARG_REG(reg2, val2)                                \
        TEST_ARG_END("")                                        \
-       TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3, 0)         \
+       TEST_BRANCH_F(code1 #reg1 code2 #reg2 code3)            \
+       TESTCASE_END
+
+#define TEST_BF_X(code, codex)                 \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_FX(code, codex)             \
+       TESTCASE_END
+
+#define TEST_BB_X(code, codex)                 \
+       TESTCASE_START(code)                    \
+       TEST_ARG_END("")                        \
+       TEST_BRANCH_BX(code, codex)             \
+       TESTCASE_END
+
+#define TEST_BF_RX(code1, reg, val, code2, codex)      \
+       TESTCASE_START(code1 #reg code2)                \
+       TEST_ARG_REG(reg, val)                          \
+       TEST_ARG_END("")                                \
+       TEST_BRANCH_FX(code1 #reg code2, codex)         \
        TESTCASE_END
 
 #define TEST_X(code, codex)                    \
@@ -372,6 +393,25 @@ struct test_arg_end {
        TESTCASE_END
 
 
+/*
+ * Macros for defining space directives spread over multiple lines.
+ * These are required so the compiler guesses better the length of inline asm
+ * code and will spill the literal pool early enough to avoid generating PC
+ * relative loads with out of range offsets.
+ */
+#define TWICE(x)       x x
+#define SPACE_0x8      TWICE(".space 4\n\t")
+#define SPACE_0x10     TWICE(SPACE_0x8)
+#define SPACE_0x20     TWICE(SPACE_0x10)
+#define SPACE_0x40     TWICE(SPACE_0x20)
+#define SPACE_0x80     TWICE(SPACE_0x40)
+#define SPACE_0x100    TWICE(SPACE_0x80)
+#define SPACE_0x200    TWICE(SPACE_0x100)
+#define SPACE_0x400    TWICE(SPACE_0x200)
+#define SPACE_0x800    TWICE(SPACE_0x400)
+#define SPACE_0x1000   TWICE(SPACE_0x800)
+
+
 /* Various values used in test cases... */
 #define N(val) (val ^ 0xffffffff)
 #define VAL1   0x12345678
index c1b4463..e59bbd4 100644 (file)
@@ -32,24 +32,6 @@ static atomic_t waiting_for_crash_ipi;
 
 int machine_kexec_prepare(struct kimage *image)
 {
-       unsigned long page_list;
-       void *reboot_code_buffer;
-       page_list = image->head & PAGE_MASK;
-
-       reboot_code_buffer = page_address(image->control_code_page);
-
-       /* Prepare parameters for reboot_code_buffer*/
-       kexec_start_address = image->start;
-       kexec_indirection_page = page_list;
-       kexec_mach_type = machine_arch_type;
-       kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
-
-       /* copy our kernel relocation code to the control code page */
-       memcpy(reboot_code_buffer,
-              relocate_new_kernel, relocate_new_kernel_size);
-
-       flush_icache_range((unsigned long) reboot_code_buffer,
-                          (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        return 0;
 }
 
@@ -100,14 +82,31 @@ void (*kexec_reinit)(void);
 
 void machine_kexec(struct kimage *image)
 {
+       unsigned long page_list;
        unsigned long reboot_code_buffer_phys;
        void *reboot_code_buffer;
 
+
+       page_list = image->head & PAGE_MASK;
+
        /* we need both effective and real address here */
        reboot_code_buffer_phys =
            page_to_pfn(image->control_code_page) << PAGE_SHIFT;
        reboot_code_buffer = page_address(image->control_code_page);
 
+       /* Prepare parameters for reboot_code_buffer*/
+       kexec_start_address = image->start;
+       kexec_indirection_page = page_list;
+       kexec_mach_type = machine_arch_type;
+       kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET;
+
+       /* copy our kernel relocation code to the control code page */
+       memcpy(reboot_code_buffer,
+              relocate_new_kernel, relocate_new_kernel_size);
+
+
+       flush_icache_range((unsigned long) reboot_code_buffer,
+                          (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        printk(KERN_INFO "Bye!\n");
 
        if (kexec_reinit)
index 24e2347..c475379 100644 (file)
@@ -343,8 +343,14 @@ validate_group(struct perf_event *event)
 {
        struct perf_event *sibling, *leader = event->group_leader;
        struct pmu_hw_events fake_pmu;
+       DECLARE_BITMAP(fake_used_mask, ARMPMU_MAX_HWEVENTS);
 
-       memset(&fake_pmu, 0, sizeof(fake_pmu));
+       /*
+        * Initialise the fake PMU. We only need to populate the
+        * used_mask for the purposes of validation.
+        */
+       memset(fake_used_mask, 0, sizeof(fake_used_mask));
+       fake_pmu.used_mask = fake_used_mask;
 
        if (!validate_event(&fake_pmu, leader))
                return -ENOSPC;
@@ -396,6 +402,9 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
        int i, err, irq, irqs;
        struct platform_device *pmu_device = armpmu->plat_device;
 
+       if (!pmu_device)
+               return -ENODEV;
+
        err = reserve_pmu(armpmu->type);
        if (err) {
                pr_warning("unable to reserve pmu\n");
index 2c3407e..2334bf8 100644 (file)
@@ -33,3 +33,4 @@ release_pmu(enum arm_pmu_type type)
 {
        clear_bit_unlock(type, pmu_lock);
 }
+EXPORT_SYMBOL_GPL(release_pmu);
index 75316f0..3d0c6fb 100644 (file)
@@ -192,6 +192,9 @@ void cpu_idle(void)
 #endif
 
                        local_irq_disable();
+#ifdef CONFIG_PL310_ERRATA_769419
+                       wmb();
+#endif
                        if (hlt_counter) {
                                local_irq_enable();
                                cpu_relax();
index 7e7977a..3448a3f 100644 (file)
@@ -461,8 +461,10 @@ static void __init setup_processor(void)
               cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
               proc_arch[cpu_architecture()], cr_alignment);
 
-       sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
-       sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
+       snprintf(init_utsname()->machine, __NEW_UTS_LEN + 1, "%s%c",
+                list->arch_name, ENDIANNESS);
+       snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c",
+                list->elf_name, ENDIANNESS);
        elf_hwcap = list->elf_hwcap;
 #ifndef CONFIG_ARM_THUMB
        elf_hwcap &= ~HWCAP_THUMB;
index 1040c00..8200dea 100644 (file)
@@ -43,7 +43,7 @@
 
 struct cputopo_arm cpu_topology[NR_CPUS];
 
-const struct cpumask *cpu_coregroup_mask(unsigned int cpu)
+const struct cpumask *cpu_coregroup_mask(int cpu)
 {
        return &cpu_topology[cpu].core_sibling;
 }
index 10d868a..d6408d1 100644 (file)
@@ -1,5 +1,9 @@
+#include <asm/unwind.h>
+
 #if __LINUX_ARM_ARCH__ >= 6
-       .macro  bitop, instr
+       .macro  bitop, name, instr
+ENTRY( \name           )
+UNWIND(        .fnstart        )
        ands    ip, r1, #3
        strneb  r1, [ip]                @ assert word-aligned
        mov     r2, #1
        cmp     r0, #0
        bne     1b
        bx      lr
+UNWIND(        .fnend          )
+ENDPROC(\name          )
        .endm
 
-       .macro  testop, instr, store
+       .macro  testop, name, instr, store
+ENTRY( \name           )
+UNWIND(        .fnstart        )
        ands    ip, r1, #3
        strneb  r1, [ip]                @ assert word-aligned
        mov     r2, #1
        cmp     r0, #0
        movne   r0, #1
 2:     bx      lr
+UNWIND(        .fnend          )
+ENDPROC(\name          )
        .endm
 #else
-       .macro  bitop, instr
+       .macro  bitop, name, instr
+ENTRY( \name           )
+UNWIND(        .fnstart        )
        ands    ip, r1, #3
        strneb  r1, [ip]                @ assert word-aligned
        and     r2, r0, #31
@@ -49,6 +61,8 @@
        str     r2, [r1, r0, lsl #2]
        restore_irqs ip
        mov     pc, lr
+UNWIND(        .fnend          )
+ENDPROC(\name          )
        .endm
 
 /**
@@ -59,7 +73,9 @@
  * Note: we can trivially conditionalise the store instruction
  * to avoid dirtying the data cache.
  */
-       .macro  testop, instr, store
+       .macro  testop, name, instr, store
+ENTRY( \name           )
+UNWIND(        .fnstart        )
        ands    ip, r1, #3
        strneb  r1, [ip]                @ assert word-aligned
        and     r3, r0, #31
@@ -73,5 +89,7 @@
        moveq   r0, #0
        restore_irqs ip
        mov     pc, lr
+UNWIND(        .fnend          )
+ENDPROC(\name          )
        .endm
 #endif
index 68ed5b6..f402786 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_change_bit)
-       bitop   eor
-ENDPROC(_change_bit)
+bitop  _change_bit, eor
index 4c04c3b..f6b75fb 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_clear_bit)
-       bitop   bic
-ENDPROC(_clear_bit)
+bitop  _clear_bit, bic
index bbee5c6..618feda 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                .text
 
-ENTRY(_set_bit)
-       bitop   orr
-ENDPROC(_set_bit)
+bitop  _set_bit, orr
index 15a4d43..4becdc3 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_change_bit)
-       testop  eor, str
-ENDPROC(_test_and_change_bit)
+testop _test_and_change_bit, eor, str
index 521b66b..918841d 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_clear_bit)
-       testop  bicne, strne
-ENDPROC(_test_and_clear_bit)
+testop _test_and_clear_bit, bicne, strne
index 1c98cc2..8d1b2fe 100644 (file)
@@ -12,6 +12,4 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_set_bit)
-       testop  orreq, streq
-ENDPROC(_test_and_set_bit)
+testop _test_and_set_bit, orreq, streq
index a4401d6..adad70d 100644 (file)
@@ -98,7 +98,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {}
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 
 static struct resource usba_udc_resources[] = {
        [0] = {
@@ -1021,8 +1021,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -1035,7 +1035,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 01d8bbd..66591fa 100644 (file)
@@ -877,8 +877,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -891,7 +891,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 24b6f8c..25e3464 100644 (file)
@@ -837,8 +837,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -851,7 +851,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 3b70b38..ae78f4d 100644 (file)
@@ -816,8 +816,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -830,7 +830,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 3faa1fd..ad017eb 100644 (file)
@@ -1196,8 +1196,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -1210,7 +1210,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 000b5e1..09a16d6 100644 (file)
@@ -197,7 +197,7 @@ void __init at91_add_device_usbh_ehci(struct at91_usbh_data *data) {}
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 static struct resource usba_udc_resources[] = {
        [0] = {
                .start  = AT91SAM9G45_UDPHS_FIFO,
@@ -1332,8 +1332,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -1346,7 +1346,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 305a851..628eb56 100644 (file)
@@ -75,7 +75,7 @@ void __init at91_add_device_hdmac(void) {}
  *  USB HS Device (Gadget)
  * -------------------------------------------------------------------- */
 
-#if defined(CONFIG_USB_GADGET_ATMEL_USBA) || defined(CONFIG_USB_GADGET_ATMEL_USBA_MODULE)
+#if defined(CONFIG_USB_ATMEL_USBA) || defined(CONFIG_USB_ATMEL_USBA_MODULE)
 
 static struct resource usba_udc_resources[] = {
        [0] = {
@@ -908,8 +908,8 @@ void __init at91_add_device_ssc(unsigned id, unsigned pins) {}
 #if defined(CONFIG_SERIAL_ATMEL)
 static struct resource dbgu_resources[] = {
        [0] = {
-               .start  = AT91_VA_BASE_SYS + AT91_DBGU,
-               .end    = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1,
+               .start  = AT91_BASE_SYS + AT91_DBGU,
+               .end    = AT91_BASE_SYS + AT91_DBGU + SZ_512 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -922,7 +922,6 @@ static struct resource dbgu_resources[] = {
 static struct atmel_uart_data dbgu_data = {
        .use_dma_tx     = 0,
        .use_dma_rx     = 0,            /* DBGU not capable of receive DMA */
-       .regs           = (void __iomem *)(AT91_VA_BASE_SYS + AT91_DBGU),
 };
 
 static u64 dbgu_dmamask = DMA_BIT_MASK(32);
index 649b052..12a3f95 100644 (file)
@@ -384,7 +384,7 @@ static struct spi_board_info yl9200_spi_devices[] = {
 #include <video/s1d13xxxfb.h>
 
 
-static void __init yl9200_init_video(void)
+static void yl9200_init_video(void)
 {
        /* NWAIT Signal */
        at91_set_A_periph(AT91_PIN_PC6, 0);
index 8eb459f..8e4a1bd 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef __ASM_ARCH_VMALLOC_H
 #define __ASM_ARCH_VMALLOC_H
 
+#include <mach/hardware.h>
+
 #define VMALLOC_END            (AT91_VIRT_BASE & PGDIR_MASK)
 
 #endif
index 43eadbc..430da12 100644 (file)
@@ -235,7 +235,7 @@ void __init bcmring_init_timer(void)
         */
        bcmring_clocksource_init();
 
-       sp804_clockevents_register(TIMER0_VA_BASE, IRQ_TIMER0, "timer0");
+       sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMER0, "timer0");
 }
 
 struct sys_timer bcmring_timer = {
index b52b8de..f4d4d6d 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/mm.h>
 #include <linux/pfn.h>
 #include <linux/atomic.h>
+#include <linux/sched.h>
 #include <mach/dma.h>
 
 /* I don't quite understand why dc4 fails when this is set to 1 and DMA is enabled */
index 35f6502..4ebb382 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/cpuidle.h>
 #include <linux/io.h>
+#include <linux/export.h>
+#include <linux/time.h>
 
 #include <asm/proc-fns.h>
 
index b82dcf0..88660d5 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
+#include <linux/smp.h>
 
 #include <asm/cacheflush.h>
 #include <asm/unified.h>
@@ -72,6 +73,9 @@ static void __init highbank_map_io(void)
 
 void highbank_set_cpu_jump(int cpu, void *jump_addr)
 {
+#ifdef CONFIG_SMP
+       cpu = cpu_logical_map(cpu);
+#endif
        writel(BSYM(virt_to_phys(jump_addr)), HB_JUMP_TABLE_VIRT(cpu));
        __cpuc_flush_dcache_area(HB_JUMP_TABLE_VIRT(cpu), 16);
        outer_clean_range(HB_JUMP_TABLE_PHYS(cpu),
index 5f7f9c2..c44aa97 100644 (file)
@@ -10,11 +10,6 @@ config HAVE_IMX_MMDC
 config HAVE_IMX_SRC
        bool
 
-#
-# ARCH_MX31 and ARCH_MX35 are left for compatibility
-# Some usages assume that having one of them implies not having (e.g.) ARCH_MX2.
-# To easily distinguish good and reviewed from unreviewed usages new (and IMHO
-# more sensible) names are used: SOC_IMX31 and SOC_IMX35
 config ARCH_MX1
        bool
 
@@ -27,12 +22,6 @@ config ARCH_MX25
 config MACH_MX27
        bool
 
-config ARCH_MX31
-       bool
-
-config ARCH_MX35
-       bool
-
 config SOC_IMX1
        bool
        select ARCH_MX1
@@ -72,7 +61,6 @@ config SOC_IMX31
        select CPU_V6
        select IMX_HAVE_PLATFORM_MXC_RNGA
        select ARCH_MXC_AUDMUX_V2
-       select ARCH_MX31
        select MXC_AVIC
        select SMP_ON_UP if SMP
 
@@ -82,7 +70,6 @@ config SOC_IMX35
        select ARCH_MXC_IOMUX_V3
        select ARCH_MXC_AUDMUX_V2
        select HAVE_EPIT
-       select ARCH_MX35
        select MXC_AVIC
        select SMP_ON_UP if SMP
 
index 22d8588..cfede57 100644 (file)
@@ -1,22 +1,26 @@
-zreladdr-$(CONFIG_ARCH_MX1)    += 0x08008000
-params_phys-$(CONFIG_ARCH_MX1) := 0x08000100
-initrd_phys-$(CONFIG_ARCH_MX1) := 0x08800000
+zreladdr-$(CONFIG_SOC_IMX1)    += 0x08008000
+params_phys-$(CONFIG_SOC_IMX1) := 0x08000100
+initrd_phys-$(CONFIG_SOC_IMX1) := 0x08800000
 
-zreladdr-$(CONFIG_MACH_MX21)   += 0xC0008000
-params_phys-$(CONFIG_MACH_MX21)        := 0xC0000100
-initrd_phys-$(CONFIG_MACH_MX21)        := 0xC0800000
+zreladdr-$(CONFIG_SOC_IMX21)   += 0xC0008000
+params_phys-$(CONFIG_SOC_IMX21)        := 0xC0000100
+initrd_phys-$(CONFIG_SOC_IMX21)        := 0xC0800000
 
-zreladdr-$(CONFIG_ARCH_MX25)   += 0x80008000
-params_phys-$(CONFIG_ARCH_MX25)        := 0x80000100
-initrd_phys-$(CONFIG_ARCH_MX25)        := 0x80800000
+zreladdr-$(CONFIG_SOC_IMX25)   += 0x80008000
+params_phys-$(CONFIG_SOC_IMX25)        := 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX25)        := 0x80800000
 
-zreladdr-$(CONFIG_MACH_MX27)   += 0xA0008000
-params_phys-$(CONFIG_MACH_MX27)        := 0xA0000100
-initrd_phys-$(CONFIG_MACH_MX27)        := 0xA0800000
+zreladdr-$(CONFIG_SOC_IMX27)   += 0xA0008000
+params_phys-$(CONFIG_SOC_IMX27)        := 0xA0000100
+initrd_phys-$(CONFIG_SOC_IMX27)        := 0xA0800000
 
-zreladdr-$(CONFIG_ARCH_MX3)    += 0x80008000
-params_phys-$(CONFIG_ARCH_MX3) := 0x80000100
-initrd_phys-$(CONFIG_ARCH_MX3) := 0x80800000
+zreladdr-$(CONFIG_SOC_IMX31)   += 0x80008000
+params_phys-$(CONFIG_SOC_IMX31)        := 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX31)        := 0x80800000
+
+zreladdr-$(CONFIG_SOC_IMX35)   += 0x80008000
+params_phys-$(CONFIG_SOC_IMX35)        := 0x80000100
+initrd_phys-$(CONFIG_SOC_IMX35)        := 0x80800000
 
 zreladdr-$(CONFIG_SOC_IMX6Q)   += 0x10008000
 params_phys-$(CONFIG_SOC_IMX6Q)        := 0x10000100
index e0b926d..039a7ab 100644 (file)
@@ -1139,7 +1139,7 @@ static int _clk_set_rate(struct clk *clk, unsigned long rate)
                return -EINVAL;
 
        max_div = ((d->bm_pred >> d->bp_pred) + 1) *
-                 ((d->bm_pred >> d->bp_pred) + 1);
+                 ((d->bm_podf >> d->bp_podf) + 1);
 
        div = parent_rate / rate;
        if (div == 0)
@@ -1953,14 +1953,17 @@ static struct map_desc imx6q_clock_desc[] = {
        imx_map_entry(MX6Q, ANATOP, MT_DEVICE),
 };
 
+void __init imx6q_clock_map_io(void)
+{
+       iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
+}
+
 int __init mx6q_clocks_init(void)
 {
        struct device_node *np;
        void __iomem *base;
        int i, irq;
 
-       iotable_init(imx6q_clock_desc, ARRAY_SIZE(imx6q_clock_desc));
-
        /* retrieve the freqency of fixed clocks from device tree */
        for_each_compatible_node(np, NULL, "fixed-clock") {
                u32 rate;
@@ -2002,6 +2005,21 @@ int __init mx6q_clocks_init(void)
        clk_set_rate(&asrc_serial_clk, 1500000);
        clk_set_rate(&enfc_clk, 11000000);
 
+       /*
+        * Before pinctrl API is available, we have to rely on the pad
+        * configuration set up by bootloader.  For usdhc example here,
+        * u-boot sets up the pads for 49.5 MHz case, and we have to lower
+        * the usdhc clock from 198 to 49.5 MHz to match the pad configuration.
+        *
+        * FIXME: This is should be removed after pinctrl API is available.
+        * At that time, usdhc driver can call pinctrl API to change pad
+        * configuration dynamically per different usdhc clock settings.
+        */
+       clk_set_rate(&usdhc1_clk, 49500000);
+       clk_set_rate(&usdhc2_clk, 49500000);
+       clk_set_rate(&usdhc3_clk, 49500000);
+       clk_set_rate(&usdhc4_clk, 49500000);
+
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
        base = of_iomap(np, 0);
        WARN_ON(!base);
index 8bf5fa3..9cd860a 100644 (file)
@@ -34,6 +34,7 @@ static void __init imx6q_map_io(void)
 {
        imx_lluart_map_io();
        imx_scu_map_io();
+       imx6q_clock_map_io();
 }
 
 static void __init imx6q_gpio_add_irq_domain(struct device_node *np,
index 9f0e82e..31807d2 100644 (file)
 static void imx3_idle(void)
 {
        unsigned long reg = 0;
-       __asm__ __volatile__(
-               /* disable I and D cache */
-               "mrc p15, 0, %0, c1, c0, 0\n"
-               "bic %0, %0, #0x00001000\n"
-               "bic %0, %0, #0x00000004\n"
-               "mcr p15, 0, %0, c1, c0, 0\n"
-               /* invalidate I cache */
-               "mov %0, #0\n"
-               "mcr p15, 0, %0, c7, c5, 0\n"
-               /* clear and invalidate D cache */
-               "mov %0, #0\n"
-               "mcr p15, 0, %0, c7, c14, 0\n"
-               /* WFI */
-               "mov %0, #0\n"
-               "mcr p15, 0, %0, c7, c0, 4\n"
-               "nop\n" "nop\n" "nop\n" "nop\n"
-               "nop\n" "nop\n" "nop\n"
-               /* enable I and D cache */
-               "mrc p15, 0, %0, c1, c0, 0\n"
-               "orr %0, %0, #0x00001000\n"
-               "orr %0, %0, #0x00000004\n"
-               "mcr p15, 0, %0, c1, c0, 0\n"
-               : "=r" (reg));
+
+       if (!need_resched())
+               __asm__ __volatile__(
+                       /* disable I and D cache */
+                       "mrc p15, 0, %0, c1, c0, 0\n"
+                       "bic %0, %0, #0x00001000\n"
+                       "bic %0, %0, #0x00000004\n"
+                       "mcr p15, 0, %0, c1, c0, 0\n"
+                       /* invalidate I cache */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c5, 0\n"
+                       /* clear and invalidate D cache */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c14, 0\n"
+                       /* WFI */
+                       "mov %0, #0\n"
+                       "mcr p15, 0, %0, c7, c0, 4\n"
+                       "nop\n" "nop\n" "nop\n" "nop\n"
+                       "nop\n" "nop\n" "nop\n"
+                       /* enable I and D cache */
+                       "mrc p15, 0, %0, c1, c0, 0\n"
+                       "orr %0, %0, #0x00001000\n"
+                       "orr %0, %0, #0x00000004\n"
+                       "mcr p15, 0, %0, c1, c0, 0\n"
+                       : "=r" (reg));
+       local_irq_enable();
 }
 
 static void __iomem *imx3_ioremap(unsigned long phys_addr, size_t size,
@@ -108,6 +111,7 @@ void imx3_init_l2x0(void)
        l2x0_init(l2x0_base, 0x00030024, 0x00000000);
 }
 
+#ifdef CONFIG_SOC_IMX31
 static struct map_desc mx31_io_desc[] __initdata = {
        imx_map_entry(MX31, X_MEMC, MT_DEVICE),
        imx_map_entry(MX31, AVIC, MT_DEVICE_NONSHARED),
@@ -126,33 +130,11 @@ void __init mx31_map_io(void)
        iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
 }
 
-static struct map_desc mx35_io_desc[] __initdata = {
-       imx_map_entry(MX35, X_MEMC, MT_DEVICE),
-       imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
-       imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
-       imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
-       imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
-};
-
-void __init mx35_map_io(void)
-{
-       iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
-}
-
 void __init imx31_init_early(void)
 {
        mxc_set_cpu_type(MXC_CPU_MX31);
        mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
-       imx_idle = imx3_idle;
-       imx_ioremap = imx3_ioremap;
-}
-
-void __init imx35_init_early(void)
-{
-       mxc_set_cpu_type(MXC_CPU_MX35);
-       mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
-       mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
-       imx_idle = imx3_idle;
+       pm_idle = imx3_idle;
        imx_ioremap = imx3_ioremap;
 }
 
@@ -161,11 +143,6 @@ void __init mx31_init_irq(void)
        mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
 }
 
-void __init mx35_init_irq(void)
-{
-       mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-}
-
 static struct sdma_script_start_addrs imx31_to1_sdma_script __initdata = {
        .per_2_per_addr = 1677,
 };
@@ -199,6 +176,35 @@ void __init imx31_soc_init(void)
 
        imx_add_imx_sdma("imx31-sdma", MX31_SDMA_BASE_ADDR, MX31_INT_SDMA, &imx31_sdma_pdata);
 }
+#endif /* ifdef CONFIG_SOC_IMX31 */
+
+#ifdef CONFIG_SOC_IMX35
+static struct map_desc mx35_io_desc[] __initdata = {
+       imx_map_entry(MX35, X_MEMC, MT_DEVICE),
+       imx_map_entry(MX35, AVIC, MT_DEVICE_NONSHARED),
+       imx_map_entry(MX35, AIPS1, MT_DEVICE_NONSHARED),
+       imx_map_entry(MX35, AIPS2, MT_DEVICE_NONSHARED),
+       imx_map_entry(MX35, SPBA0, MT_DEVICE_NONSHARED),
+};
+
+void __init mx35_map_io(void)
+{
+       iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
+}
+
+void __init imx35_init_early(void)
+{
+       mxc_set_cpu_type(MXC_CPU_MX35);
+       mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
+       mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
+       pm_idle = imx3_idle;
+       imx_ioremap = imx3_ioremap;
+}
+
+void __init mx35_init_irq(void)
+{
+       mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
+}
 
 static struct sdma_script_start_addrs imx35_to1_sdma_script __initdata = {
        .ap_2_ap_addr = 642,
@@ -254,3 +260,4 @@ void __init imx35_soc_init(void)
 
        imx_add_imx_sdma("imx35-sdma", MX35_SDMA_BASE_ADDR, MX35_INT_SDMA, &imx35_sdma_pdata);
 }
+#endif /* ifdef CONFIG_SOC_IMX35 */
index 36cacbd..a8e3368 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/smp.h>
 #include <asm/unified.h>
 
 #define SRC_SCR                                0x000
 
 static void __iomem *src_base;
 
+#ifndef CONFIG_SMP
+#define cpu_logical_map(cpu)           0
+#endif
+
 void imx_enable_cpu(int cpu, bool enable)
 {
        u32 mask, val;
 
+       cpu = cpu_logical_map(cpu);
        mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
        val = readl_relaxed(src_base + SRC_SCR);
        val = enable ? val | mask : val & ~mask;
@@ -35,6 +41,7 @@ void imx_enable_cpu(int cpu, bool enable)
 
 void imx_set_cpu_jump(int cpu, void *jump_addr)
 {
+       cpu = cpu_logical_map(cpu);
        writel_relaxed(BSYM(virt_to_phys(jump_addr)),
                       src_base + SRC_GPR1 + cpu * 8);
 }
index 6915656..4665767 100644 (file)
@@ -182,7 +182,7 @@ static void __init gplugd_init(void)
 
        /* on-chip devices */
        pxa168_add_uart(3);
-       pxa168_add_ssp(0);
+       pxa168_add_ssp(1);
        pxa168_add_twsi(0, NULL, ARRAY_AND_SIZE(gplugd_i2c_board_info));
 
        pxa168_add_eth(&gplugd_eth_platform_data);
index d14eeaf..99b4ce1 100644 (file)
@@ -7,7 +7,7 @@
 #define GPIO_REGS_VIRT (APB_VIRT_BASE + 0x19000)
 
 #define BANK_OFF(n)    (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
-#define GPIO_REG(x)    (GPIO_REGS_VIRT + (x))
+#define GPIO_REG(x)    (*(volatile u32 *)(GPIO_REGS_VIRT + (x)))
 
 #define NR_BUILTIN_GPIO                IRQ_GPIO_NUM
 
index 4285dfd..4ad3969 100644 (file)
@@ -15,6 +15,8 @@ obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
 obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
 
+CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1)
+
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 
index 71de506..db81ed5 100644 (file)
@@ -42,8 +42,8 @@
 
 extern struct sys_timer msm_timer;
 
-static void __init msm7x30_fixup(struct machine_desc *desc, struct tag *tag,
-                        char **cmdline, struct meminfo *mi)
+static void __init msm7x30_fixup(struct tag *tag, char **cmdline,
+               struct meminfo *mi)
 {
        for (; tag->hdr.size; tag = tag_next(tag))
                if (tag->hdr.tag == ATAG_MEM && tag->u.mem.start == 0x200000) {
index b04468e..6dc1cbd 100644 (file)
@@ -32,8 +32,8 @@
 
 #include "devices.h"
 
-static void __init msm8960_fixup(struct machine_desc *desc, struct tag *tag,
-                        char **cmdline, struct meminfo *mi)
+static void __init msm8960_fixup(struct tag *tag, char **cmdline,
+               struct meminfo *mi)
 {
        for (; tag->hdr.size; tag = tag_next(tag))
                if (tag->hdr.tag == ATAG_MEM &&
index cf38e22..44bf716 100644 (file)
@@ -28,8 +28,8 @@
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
-static void __init msm8x60_fixup(struct machine_desc *desc, struct tag *tag,
-                        char **cmdline, struct meminfo *mi)
+static void __init msm8x60_fixup(struct tag *tag, char **cmdline,
+               struct meminfo *mi)
 {
        for (; tag->hdr.size; tag = tag_next(tag))
                if (tag->hdr.tag == ATAG_MEM &&
index 232f97a..bafabb5 100644 (file)
@@ -180,6 +180,9 @@ static u32 smc(u32 cmd_addr)
                        __asmeq("%1", "r0")
                        __asmeq("%2", "r1")
                        __asmeq("%3", "r2")
+#ifdef REQUIRES_SEC
+                       ".arch_extension sec\n"
+#endif
                        "smc    #0      @ switch to secure world\n"
                        : "=r" (r0)
                        : "r" (r0), "r" (r1), "r" (r2)
index 2aacf41..4cb2769 100644 (file)
@@ -1281,9 +1281,9 @@ DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,
        NULL,  NULL, &ipg_clk, &gpt_ipg_clk);
 
 DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,
-       NULL, NULL, &ipg_clk, NULL);
+       NULL, NULL, &ipg_perclk, NULL);
 DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,
-       NULL, NULL, &ipg_clk, NULL);
+       NULL, NULL, &ipg_perclk, NULL);
 
 /* I2C */
 DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,
@@ -1634,6 +1634,7 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,
        return 0;
 }
 
+#ifdef CONFIG_OF
 static void __init clk_get_freq_dt(unsigned long *ckil, unsigned long *osc,
                                   unsigned long *ckih1, unsigned long *ckih2)
 {
@@ -1671,3 +1672,4 @@ int __init mx53_clocks_init_dt(void)
        clk_get_freq_dt(&ckil, &osc, &ckih1, &ckih2);
        return mx53_clocks_init(ckil, osc, ckih1, ckih2);
 }
+#endif
index 5c53282..5e2e7a8 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <mach/hardware.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 static int mx5_cpu_rev = -1;
 
@@ -67,7 +67,8 @@ static int __init mx51_neon_fixup(void)
        if (!cpu_is_mx51())
                return 0;
 
-       if (mx51_revision() < IMX_CHIP_REVISION_3_0 && (elf_hwcap & HWCAP_NEON)) {
+       if (mx51_revision() < IMX_CHIP_REVISION_3_0 &&
+                       (elf_hwcap & HWCAP_NEON)) {
                elf_hwcap &= ~HWCAP_NEON;
                pr_info("Turning off NEON support, detected broken NEON implementation\n");
        }
index 26eacc9..df4a508 100644 (file)
@@ -23,7 +23,9 @@
 
 static void imx5_idle(void)
 {
-       mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+       if (!need_resched())
+               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+       local_irq_enable();
 }
 
 /*
@@ -89,7 +91,7 @@ void __init imx51_init_early(void)
        mxc_set_cpu_type(MXC_CPU_MX51);
        mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
        mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-       imx_idle = imx5_idle;
+       pm_idle = imx5_idle;
 }
 
 void __init imx53_init_early(void)
index 229ae34..da6e4aa 100644 (file)
@@ -404,7 +404,7 @@ static int name##_set_rate(struct clk *clk, unsigned long rate)             \
        reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_##dr);         \
        reg &= ~BM_CLKCTRL_##dr##_DIV;                                  \
        reg |= div << BP_CLKCTRL_##dr##_DIV;                            \
-       if (reg | (1 << clk->enable_shift)) {                           \
+       if (reg & (1 << clk->enable_shift)) {                           \
                pr_err("%s: clock is gated\n", __func__);               \
                return -EINVAL;                                         \
        }                                                               \
index ac2316d..064ec5a 100644 (file)
@@ -471,7 +471,8 @@ static void __init mx28evk_init(void)
                               "mmc0-slot-power");
        if (ret)
                pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret);
-       mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
+       else
+               mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
 
        ret = gpio_request_one(MX28EVK_MMC1_SLOT_POWER, GPIOF_OUT_INIT_LOW,
                               "mmc1-slot-power");
@@ -480,7 +481,6 @@ static void __init mx28evk_init(void)
        else
                mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
 
-       mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
        mx28_add_rtc_stmp3xxx();
 
        gpio_led_register_device(0, &mx28evk_led_data);
index e0a0281..73f287d 100644 (file)
@@ -171,14 +171,6 @@ config MACH_OMAP_GENERIC
 comment "OMAP CPU Speed"
        depends on ARCH_OMAP1
 
-config OMAP_CLOCKS_SET_BY_BOOTLOADER
-       bool "OMAP clocks set by bootloader"
-       depends on ARCH_OMAP1
-       help
-         Enable this option to prevent the kernel from overriding the clock
-         frequencies programmed by bootloader for MPU, DSP, MMUs, TC,
-         internal LCD controller and MPU peripherals.
-
 config OMAP_ARM_216MHZ
        bool "OMAP ARM 216 MHz CPU (1710 only)"
         depends on ARCH_OMAP1 && ARCH_OMAP16XX
index 51bae31..b0f15d2 100644 (file)
@@ -302,8 +302,6 @@ static void __init ams_delta_init(void)
        omap_cfg_reg(J19_1610_CAM_D6);
        omap_cfg_reg(J18_1610_CAM_D7);
 
-       iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
-
        omap_board_config = ams_delta_config;
        omap_board_config_size = ARRAY_SIZE(ams_delta_config);
        omap_serial_init();
@@ -373,10 +371,16 @@ static int __init ams_delta_modem_init(void)
 }
 arch_initcall(ams_delta_modem_init);
 
+static void __init ams_delta_map_io(void)
+{
+       omap15xx_map_io();
+       iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
+}
+
 MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
        /* Maintainer: Jonathan McDowell <noodles@earth.li> */
        .atag_offset    = 0x100,
-       .map_io         = omap15xx_map_io,
+       .map_io         = ams_delta_map_io,
        .init_early     = omap1_init_early,
        .reserve        = omap_reserve,
        .init_irq       = omap1_init_irq,
index eaf09ef..16b1423 100644 (file)
@@ -17,7 +17,8 @@
 
 #include <plat/clock.h>
 
-extern int __init omap1_clk_init(void);
+int omap1_clk_init(void);
+void omap1_clk_late_init(void);
 extern int omap1_clk_enable(struct clk *clk);
 extern void omap1_clk_disable(struct clk *clk);
 extern long omap1_clk_round_rate(struct clk *clk, unsigned long rate);
index 92400b9..1297bb5 100644 (file)
@@ -767,6 +767,15 @@ static struct clk_functions omap1_clk_functions = {
        .clk_disable_unused     = omap1_clk_disable_unused,
 };
 
+static void __init omap1_show_rates(void)
+{
+       pr_notice("Clocking rate (xtal/DPLL1/MPU): "
+                       "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
+               ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
+               ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
+               arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
+}
+
 int __init omap1_clk_init(void)
 {
        struct omap_clk *c;
@@ -835,9 +844,12 @@ int __init omap1_clk_init(void)
        /* We want to be in syncronous scalable mode */
        omap_writew(0x1000, ARM_SYSST);
 
-#ifdef CONFIG_OMAP_CLOCKS_SET_BY_BOOTLOADER
-       /* Use values set by bootloader. Determine PLL rate and recalculate
-        * dependent clocks as if kernel had changed PLL or divisors.
+
+       /*
+        * Initially use the values set by bootloader. Determine PLL rate and
+        * recalculate dependent clocks as if kernel had changed PLL or
+        * divisors. See also omap1_clk_late_init() that can reprogram dpll1
+        * after the SRAM is initialized.
         */
        {
                unsigned pll_ctl_val = omap_readw(DPLL_CTL);
@@ -862,25 +874,10 @@ int __init omap1_clk_init(void)
                        }
                }
        }
-#else
-       /* Find the highest supported frequency and enable it */
-       if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
-               printk(KERN_ERR "System frequencies not set. Check your config.\n");
-               /* Guess sane values (60MHz) */
-               omap_writew(0x2290, DPLL_CTL);
-               omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
-               ck_dpll1.rate = 60000000;
-       }
-#endif
        propagate_rate(&ck_dpll1);
        /* Cache rates for clocks connected to ck_ref (not dpll1) */
        propagate_rate(&ck_ref);
-       printk(KERN_INFO "Clocking rate (xtal/DPLL1/MPU): "
-               "%ld.%01ld/%ld.%01ld/%ld.%01ld MHz\n",
-              ck_ref.rate / 1000000, (ck_ref.rate / 100000) % 10,
-              ck_dpll1.rate / 1000000, (ck_dpll1.rate / 100000) % 10,
-              arm_ck.rate / 1000000, (arm_ck.rate / 100000) % 10);
-
+       omap1_show_rates();
        if (machine_is_omap_perseus2() || machine_is_omap_fsample()) {
                /* Select slicer output as OMAP input clock */
                omap_writew(omap_readw(OMAP7XX_PCC_UPLD_CTRL) & ~0x1,
@@ -925,3 +922,21 @@ int __init omap1_clk_init(void)
 
        return 0;
 }
+
+#define OMAP1_DPLL1_SANE_VALUE 60000000
+
+void __init omap1_clk_late_init(void)
+{
+       if (ck_dpll1.rate >= OMAP1_DPLL1_SANE_VALUE)
+               return;
+
+       /* Find the highest supported frequency and enable it */
+       if (omap1_select_table_rate(&virtual_ck_mpu, ~0)) {
+               pr_err("System frequencies not set, using default. Check your config.\n");
+               omap_writew(0x2290, DPLL_CTL);
+               omap_writew(cpu_is_omap7xx() ? 0x3005 : 0x1005, ARM_CKCTL);
+               ck_dpll1.rate = OMAP1_DPLL1_SANE_VALUE;
+       }
+       propagate_rate(&ck_dpll1);
+       omap1_show_rates();
+}
index 48ef988..475cb2f 100644 (file)
@@ -30,6 +30,8 @@
 #include <plat/omap7xx.h>
 #include <plat/mcbsp.h>
 
+#include "clock.h"
+
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_RTC_DRV_OMAP) || defined(CONFIG_RTC_DRV_OMAP_MODULE)
@@ -293,6 +295,7 @@ static int __init omap1_init_devices(void)
                return -ENODEV;
 
        omap_sram_init();
+       omap1_clk_late_init();
 
        /* please keep these calls, and their implementations above,
         * in alphabetical order so they're easier to sort through.
index 5034147..e1293aa 100644 (file)
@@ -334,6 +334,7 @@ config MACH_OMAP4_PANDA
 config OMAP3_EMU
        bool "OMAP3 debugging peripherals"
        depends on ARCH_OMAP3
+       select ARM_AMBA
        select OC_ETM
        help
          Say Y here to enable debugging hardware of omap3
index 69ab1c0..b009f17 100644 (file)
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
-        common.o gpio.o dma.o wd_timer.o
+        common.o gpio.o dma.o wd_timer.o display.o
 
 omap-2-3-common                                = irq.o sdrc.o
 hwmod-common                           = omap_hwmod.o \
@@ -264,7 +264,4 @@ smsc911x-$(CONFIG_SMSC911X)         := gpmc-smsc911x.o
 obj-y                                  += $(smsc911x-m) $(smsc911x-y)
 obj-$(CONFIG_ARCH_OMAP4)               += hwspinlock.o
 
-disp-$(CONFIG_OMAP2_DSS)               := display.o
-obj-y                                  += $(disp-m) $(disp-y)
-
 obj-y                                  += common-board-devices.o twl-common.o
index 1fe35c2..942bb4f 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/sched.h>
 #include <linux/cpuidle.h>
+#include <linux/export.h>
 
 #include <plat/prcm.h>
 #include <plat/irqs.h>
index adb2756..dce9905 100644 (file)
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
 #include <plat/omap-pm.h>
+#include <plat/common.h>
 
 #include "control.h"
+#include "display.h"
+
+#define DISPC_CONTROL          0x0040
+#define DISPC_CONTROL2         0x0238
+#define DISPC_IRQSTATUS                0x0018
+
+#define DSS_SYSCONFIG          0x10
+#define DSS_SYSSTATUS          0x14
+#define DSS_CONTROL            0x40
+#define DSS_SDI_CONTROL                0x44
+#define DSS_PLL_CONTROL                0x48
+
+#define LCD_EN_MASK            (0x1 << 0)
+#define DIGIT_EN_MASK          (0x1 << 1)
+
+#define FRAMEDONE_IRQ_SHIFT    0
+#define EVSYNC_EVEN_IRQ_SHIFT  2
+#define EVSYNC_ODD_IRQ_SHIFT   3
+#define FRAMEDONE2_IRQ_SHIFT   22
+#define FRAMEDONETV_IRQ_SHIFT  24
+
+/*
+ * FRAMEDONE_IRQ_TIMEOUT: how long (in milliseconds) to wait during DISPC
+ *     reset before deciding that something has gone wrong
+ */
+#define FRAMEDONE_IRQ_TIMEOUT          100
 
 static struct platform_device omap_display_device = {
        .name          = "omapdss",
@@ -172,3 +199,135 @@ int __init omap_display_init(struct omap_dss_board_info *board_data)
 
        return r;
 }
+
+static void dispc_disable_outputs(void)
+{
+       u32 v, irq_mask = 0;
+       bool lcd_en, digit_en, lcd2_en = false;
+       int i;
+       struct omap_dss_dispc_dev_attr *da;
+       struct omap_hwmod *oh;
+
+       oh = omap_hwmod_lookup("dss_dispc");
+       if (!oh) {
+               WARN(1, "display: could not disable outputs during reset - could not find dss_dispc hwmod\n");
+               return;
+       }
+
+       if (!oh->dev_attr) {
+               pr_err("display: could not disable outputs during reset due to missing dev_attr\n");
+               return;
+       }
+
+       da = (struct omap_dss_dispc_dev_attr *)oh->dev_attr;
+
+       /* store value of LCDENABLE and DIGITENABLE bits */
+       v = omap_hwmod_read(oh, DISPC_CONTROL);
+       lcd_en = v & LCD_EN_MASK;
+       digit_en = v & DIGIT_EN_MASK;
+
+       /* store value of LCDENABLE for LCD2 */
+       if (da->manager_count > 2) {
+               v = omap_hwmod_read(oh, DISPC_CONTROL2);
+               lcd2_en = v & LCD_EN_MASK;
+       }
+
+       if (!(lcd_en | digit_en | lcd2_en))
+               return; /* no managers currently enabled */
+
+       /*
+        * If any manager was enabled, we need to disable it before
+        * DSS clocks are disabled or DISPC module is reset
+        */
+       if (lcd_en)
+               irq_mask |= 1 << FRAMEDONE_IRQ_SHIFT;
+
+       if (digit_en) {
+               if (da->has_framedonetv_irq) {
+                       irq_mask |= 1 << FRAMEDONETV_IRQ_SHIFT;
+               } else {
+                       irq_mask |= 1 << EVSYNC_EVEN_IRQ_SHIFT |
+                               1 << EVSYNC_ODD_IRQ_SHIFT;
+               }
+       }
+
+       if (lcd2_en)
+               irq_mask |= 1 << FRAMEDONE2_IRQ_SHIFT;
+
+       /*
+        * clear any previous FRAMEDONE, FRAMEDONETV,
+        * EVSYNC_EVEN/ODD or FRAMEDONE2 interrupts
+        */
+       omap_hwmod_write(irq_mask, oh, DISPC_IRQSTATUS);
+
+       /* disable LCD and TV managers */
+       v = omap_hwmod_read(oh, DISPC_CONTROL);
+       v &= ~(LCD_EN_MASK | DIGIT_EN_MASK);
+       omap_hwmod_write(v, oh, DISPC_CONTROL);
+
+       /* disable LCD2 manager */
+       if (da->manager_count > 2) {
+               v = omap_hwmod_read(oh, DISPC_CONTROL2);
+               v &= ~LCD_EN_MASK;
+               omap_hwmod_write(v, oh, DISPC_CONTROL2);
+       }
+
+       i = 0;
+       while ((omap_hwmod_read(oh, DISPC_IRQSTATUS) & irq_mask) !=
+              irq_mask) {
+               i++;
+               if (i > FRAMEDONE_IRQ_TIMEOUT) {
+                       pr_err("didn't get FRAMEDONE1/2 or TV interrupt\n");
+                       break;
+               }
+               mdelay(1);
+       }
+}
+
+#define MAX_MODULE_SOFTRESET_WAIT      10000
+int omap_dss_reset(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_opt_clk *oc;
+       int c = 0;
+       int i, r;
+
+       if (!(oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)) {
+               pr_err("dss_core: hwmod data doesn't contain reset data\n");
+               return -EINVAL;
+       }
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk)
+                       clk_enable(oc->_clk);
+
+       dispc_disable_outputs();
+
+       /* clear SDI registers */
+       if (cpu_is_omap3430()) {
+               omap_hwmod_write(0x0, oh, DSS_SDI_CONTROL);
+               omap_hwmod_write(0x0, oh, DSS_PLL_CONTROL);
+       }
+
+       /*
+        * clear DSS_CONTROL register to switch DSS clock sources to
+        * PRCM clock, if any
+        */
+       omap_hwmod_write(0x0, oh, DSS_CONTROL);
+
+       omap_test_timeout((omap_hwmod_read(oh, oh->class->sysc->syss_offs)
+                               & SYSS_RESETDONE_MASK),
+                       MAX_MODULE_SOFTRESET_WAIT, c);
+
+       if (c == MAX_MODULE_SOFTRESET_WAIT)
+               pr_warning("dss_core: waiting for reset to finish failed\n");
+       else
+               pr_debug("dss_core: softreset done\n");
+
+       for (i = oh->opt_clks_cnt, oc = oh->opt_clks; i > 0; i--, oc++)
+               if (oc->_clk)
+                       clk_disable(oc->_clk);
+
+       r = (c == MAX_MODULE_SOFTRESET_WAIT) ? -ETIMEDOUT : 0;
+
+       return r;
+}
diff --git a/arch/arm/mach-omap2/display.h b/arch/arm/mach-omap2/display.h
new file mode 100644 (file)
index 0000000..b871b01
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * display.h - OMAP2+ integration-specific DSS header
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+#define __ARCH_ARM_MACH_OMAP2_DISPLAY_H
+
+#include <linux/kernel.h>
+
+struct omap_dss_dispc_dev_attr {
+       u8      manager_count;
+       bool    has_framedonetv_irq;
+};
+
+#endif
diff --git a/arch/arm/mach-omap2/io.h b/arch/arm/mach-omap2/io.h
deleted file mode 100644 (file)
index e69de29..0000000
index 6b3088d..207a2ff 100644 (file)
@@ -749,7 +749,7 @@ static int _count_mpu_irqs(struct omap_hwmod *oh)
                ohii = &oh->mpu_irqs[i++];
        } while (ohii->irq != -1);
 
-       return i;
+       return i-1;
 }
 
 /**
@@ -772,7 +772,7 @@ static int _count_sdma_reqs(struct omap_hwmod *oh)
                ohdi = &oh->sdma_reqs[i++];
        } while (ohdi->dma_req != -1);
 
-       return i;
+       return i-1;
 }
 
 /**
@@ -795,7 +795,7 @@ static int _count_ocp_if_addr_spaces(struct omap_hwmod_ocp_if *os)
                mem = &os->addr[i++];
        } while (mem->pa_start != mem->pa_end);
 
-       return i;
+       return i-1;
 }
 
 /**
index 6d72062..a5409ce 100644 (file)
@@ -875,6 +875,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+       /*
+        * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+        * driver does not use these clocks.
+        */
        { .role = "tv_clk", .clk = "dss_54m_fck" },
        { .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -899,7 +903,7 @@ static struct omap_hwmod omap2420_dss_core_hwmod = {
        .slaves_cnt     = ARRAY_SIZE(omap2420_dss_slaves),
        .masters        = omap2420_dss_masters,
        .masters_cnt    = ARRAY_SIZE(omap2420_dss_masters),
-       .flags          = HWMOD_NO_IDLEST,
+       .flags          = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 /* l4_core -> dss_dispc */
@@ -939,6 +943,7 @@ static struct omap_hwmod omap2420_dss_dispc_hwmod = {
        .slaves         = omap2420_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_dss_dispc_slaves),
        .flags          = HWMOD_NO_IDLEST,
+       .dev_attr       = &omap2_3_dss_dispc_dev_attr
 };
 
 /* l4_core -> dss_rfbi */
@@ -961,6 +966,10 @@ static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
        &omap2420_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+       { .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
        .name           = "dss_rfbi",
        .class          = &omap2_rfbi_hwmod_class,
@@ -972,6 +981,8 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
                        .module_offs = CORE_MOD,
                },
        },
+       .opt_clks       = dss_rfbi_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
        .slaves         = omap2420_dss_rfbi_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2420_dss_rfbi_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -981,7 +992,7 @@ static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
 static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
        .master         = &omap2420_l4_core_hwmod,
        .slave          = &omap2420_dss_venc_hwmod,
-       .clk            = "dss_54m_fck",
+       .clk            = "dss_ick",
        .addr           = omap2_dss_venc_addrs,
        .fw = {
                .omap2 = {
@@ -1001,7 +1012,7 @@ static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
 static struct omap_hwmod omap2420_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap2_venc_hwmod_class,
-       .main_clk       = "dss1_fck",
+       .main_clk       = "dss_54m_fck",
        .prcm           = {
                .omap2 = {
                        .prcm_reg_id = 1,
index a2580d0..c4f56cb 100644 (file)
@@ -942,6 +942,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+       /*
+        * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+        * driver does not use these clocks.
+        */
        { .role = "tv_clk", .clk = "dss_54m_fck" },
        { .role = "sys_clk", .clk = "dss2_fck" },
 };
@@ -966,7 +970,7 @@ static struct omap_hwmod omap2430_dss_core_hwmod = {
        .slaves_cnt     = ARRAY_SIZE(omap2430_dss_slaves),
        .masters        = omap2430_dss_masters,
        .masters_cnt    = ARRAY_SIZE(omap2430_dss_masters),
-       .flags          = HWMOD_NO_IDLEST,
+       .flags          = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 /* l4_core -> dss_dispc */
@@ -1000,6 +1004,7 @@ static struct omap_hwmod omap2430_dss_dispc_hwmod = {
        .slaves         = omap2430_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_dss_dispc_slaves),
        .flags          = HWMOD_NO_IDLEST,
+       .dev_attr       = &omap2_3_dss_dispc_dev_attr
 };
 
 /* l4_core -> dss_rfbi */
@@ -1016,6 +1021,10 @@ static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
        &omap2430_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+       { .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
        .name           = "dss_rfbi",
        .class          = &omap2_rfbi_hwmod_class,
@@ -1027,6 +1036,8 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
                        .module_offs = CORE_MOD,
                },
        },
+       .opt_clks       = dss_rfbi_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
        .slaves         = omap2430_dss_rfbi_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap2430_dss_rfbi_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -1036,7 +1047,7 @@ static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
 static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
        .master         = &omap2430_l4_core_hwmod,
        .slave          = &omap2430_dss_venc_hwmod,
-       .clk            = "dss_54m_fck",
+       .clk            = "dss_ick",
        .addr           = omap2_dss_venc_addrs,
        .flags          = OCPIF_SWSUP_IDLE,
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
@@ -1050,7 +1061,7 @@ static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
 static struct omap_hwmod omap2430_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap2_venc_hwmod_class,
-       .main_clk       = "dss1_fck",
+       .main_clk       = "dss_54m_fck",
        .prcm           = {
                .omap2 = {
                        .prcm_reg_id = 1,
index c451729..c11273d 100644 (file)
@@ -11,6 +11,7 @@
 #include <plat/omap_hwmod.h>
 #include <plat/serial.h>
 #include <plat/dma.h>
+#include <plat/common.h>
 
 #include <mach/irqs.h>
 
@@ -43,13 +44,15 @@ static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
        .rev_offs       = 0x0000,
        .sysc_offs      = 0x0010,
        .syss_offs      = 0x0014,
-       .sysc_flags     = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+       .sysc_flags     = (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+                          SYSS_HAS_RESET_STATUS),
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
 struct omap_hwmod_class omap2_dss_hwmod_class = {
        .name   = "dss",
        .sysc   = &omap2_dss_sysc,
+       .reset  = omap_dss_reset,
 };
 
 /*
index bc9035e..7f8915a 100644 (file)
@@ -1369,9 +1369,14 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
 };
 
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
-       { .role = "tv_clk", .clk = "dss_tv_fck" },
-       { .role = "video_clk", .clk = "dss_96m_fck" },
+       /*
+        * The DSS HW needs all DSS clocks enabled during reset. The dss_core
+        * driver does not use these clocks.
+        */
        { .role = "sys_clk", .clk = "dss2_alwon_fck" },
+       { .role = "tv_clk", .clk = "dss_tv_fck" },
+       /* required only on OMAP3430 */
+       { .role = "tv_dac_clk", .clk = "dss_96m_fck" },
 };
 
 static struct omap_hwmod omap3430es1_dss_core_hwmod = {
@@ -1394,11 +1399,12 @@ static struct omap_hwmod omap3430es1_dss_core_hwmod = {
        .slaves_cnt     = ARRAY_SIZE(omap3430es1_dss_slaves),
        .masters        = omap3xxx_dss_masters,
        .masters_cnt    = ARRAY_SIZE(omap3xxx_dss_masters),
-       .flags          = HWMOD_NO_IDLEST,
+       .flags          = HWMOD_NO_IDLEST | HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 };
 
 static struct omap_hwmod omap3xxx_dss_core_hwmod = {
        .name           = "dss_core",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .class          = &omap2_dss_hwmod_class,
        .main_clk       = "dss1_alwon_fck", /* instead of dss_fck */
        .sdma_reqs      = omap3xxx_dss_sdma_chs,
@@ -1456,6 +1462,7 @@ static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
        .slaves         = omap3xxx_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
        .flags          = HWMOD_NO_IDLEST,
+       .dev_attr       = &omap2_3_dss_dispc_dev_attr
 };
 
 /*
@@ -1486,6 +1493,7 @@ static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &omap3xxx_dss_dsi1_hwmod,
+       .clk            = "dss_ick",
        .addr           = omap3xxx_dss_dsi1_addrs,
        .fw = {
                .omap2 = {
@@ -1502,6 +1510,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
        &omap3xxx_l4_core__dss_dsi1,
 };
 
+static struct omap_hwmod_opt_clk dss_dsi1_opt_clks[] = {
+       { .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
        .name           = "dss_dsi1",
        .class          = &omap3xxx_dsi_hwmod_class,
@@ -1514,6 +1526,8 @@ static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
                        .module_offs = OMAP3430_DSS_MOD,
                },
        },
+       .opt_clks       = dss_dsi1_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_dsi1_opt_clks),
        .slaves         = omap3xxx_dss_dsi1_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -1540,6 +1554,10 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
        &omap3xxx_l4_core__dss_rfbi,
 };
 
+static struct omap_hwmod_opt_clk dss_rfbi_opt_clks[] = {
+       { .role = "ick", .clk = "dss_ick" },
+};
+
 static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
        .name           = "dss_rfbi",
        .class          = &omap2_rfbi_hwmod_class,
@@ -1551,6 +1569,8 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
                        .module_offs = OMAP3430_DSS_MOD,
                },
        },
+       .opt_clks       = dss_rfbi_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_rfbi_opt_clks),
        .slaves         = omap3xxx_dss_rfbi_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
        .flags          = HWMOD_NO_IDLEST,
@@ -1560,7 +1580,7 @@ static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &omap3xxx_dss_venc_hwmod,
-       .clk            = "dss_tv_fck",
+       .clk            = "dss_ick",
        .addr           = omap2_dss_venc_addrs,
        .fw = {
                .omap2 = {
@@ -1578,10 +1598,15 @@ static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
        &omap3xxx_l4_core__dss_venc,
 };
 
+static struct omap_hwmod_opt_clk dss_venc_opt_clks[] = {
+       /* required only on OMAP3430 */
+       { .role = "tv_dac_clk", .clk = "dss_96m_fck" },
+};
+
 static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap2_venc_hwmod_class,
-       .main_clk       = "dss1_alwon_fck",
+       .main_clk       = "dss_tv_fck",
        .prcm           = {
                .omap2 = {
                        .prcm_reg_id = 1,
@@ -1589,6 +1614,8 @@ static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
                        .module_offs = OMAP3430_DSS_MOD,
                },
        },
+       .opt_clks       = dss_venc_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(dss_venc_opt_clks),
        .slaves         = omap3xxx_dss_venc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap3xxx_dss_venc_slaves),
        .flags          = HWMOD_NO_IDLEST,
index 7695e5d..daaf165 100644 (file)
@@ -30,6 +30,7 @@
 #include <plat/mmc.h>
 #include <plat/i2c.h>
 #include <plat/dmtimer.h>
+#include <plat/common.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -1187,6 +1188,7 @@ static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = {
 static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
        .name   = "dss",
        .sysc   = &omap44xx_dss_sysc,
+       .reset  = omap_dss_reset,
 };
 
 /* dss */
@@ -1240,12 +1242,12 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = {
 static struct omap_hwmod_opt_clk dss_opt_clks[] = {
        { .role = "sys_clk", .clk = "dss_sys_clk" },
        { .role = "tv_clk", .clk = "dss_tv_clk" },
-       { .role = "dss_clk", .clk = "dss_dss_clk" },
-       { .role = "video_clk", .clk = "dss_48mhz_clk" },
+       { .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
 };
 
 static struct omap_hwmod omap44xx_dss_hwmod = {
        .name           = "dss_core",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .class          = &omap44xx_dss_hwmod_class,
        .clkdm_name     = "l3_dss_clkdm",
        .main_clk       = "dss_dss_clk",
@@ -1325,6 +1327,11 @@ static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = {
        { }
 };
 
+static struct omap_dss_dispc_dev_attr omap44xx_dss_dispc_dev_attr = {
+       .manager_count          = 3,
+       .has_framedonetv_irq    = 1
+};
+
 /* l4_per -> dss_dispc */
 static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
        .master         = &omap44xx_l4_per_hwmod,
@@ -1340,12 +1347,6 @@ static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
        &omap44xx_l4_per__dss_dispc,
 };
 
-static struct omap_hwmod_opt_clk dss_dispc_opt_clks[] = {
-       { .role = "sys_clk", .clk = "dss_sys_clk" },
-       { .role = "tv_clk", .clk = "dss_tv_clk" },
-       { .role = "hdmi_clk", .clk = "dss_48mhz_clk" },
-};
-
 static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
        .name           = "dss_dispc",
        .class          = &omap44xx_dispc_hwmod_class,
@@ -1359,10 +1360,9 @@ static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
                        .context_offs = OMAP4_RM_DSS_DSS_CONTEXT_OFFSET,
                },
        },
-       .opt_clks       = dss_dispc_opt_clks,
-       .opt_clks_cnt   = ARRAY_SIZE(dss_dispc_opt_clks),
        .slaves         = omap44xx_dss_dispc_slaves,
        .slaves_cnt     = ARRAY_SIZE(omap44xx_dss_dispc_slaves),
+       .dev_attr       = &omap44xx_dss_dispc_dev_attr
 };
 
 /*
@@ -1624,7 +1624,7 @@ static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
        .clkdm_name     = "l3_dss_clkdm",
        .mpu_irqs       = omap44xx_dss_hdmi_irqs,
        .sdma_reqs      = omap44xx_dss_hdmi_sdma_reqs,
-       .main_clk       = "dss_dss_clk",
+       .main_clk       = "dss_48mhz_clk",
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
@@ -1785,7 +1785,7 @@ static struct omap_hwmod omap44xx_dss_venc_hwmod = {
        .name           = "dss_venc",
        .class          = &omap44xx_venc_hwmod_class,
        .clkdm_name     = "l3_dss_clkdm",
-       .main_clk       = "dss_dss_clk",
+       .main_clk       = "dss_tv_clk",
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = OMAP4_CM_DSS_DSS_CLKCTRL_OFFSET,
index de832eb..51e5418 100644 (file)
@@ -49,3 +49,7 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = {
        .srst_shift     = SYSC_TYPE2_SOFTRESET_SHIFT,
 };
 
+struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = {
+       .manager_count          = 2,
+       .has_framedonetv_irq    = 0
+};
index 39a7c37..ad5d8f0 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <plat/omap_hwmod.h>
 
+#include "display.h"
+
 /* Common address space across OMAP2xxx */
 extern struct omap_hwmod_addr_space omap2xxx_uart1_addr_space[];
 extern struct omap_hwmod_addr_space omap2xxx_uart2_addr_space[];
@@ -111,4 +113,6 @@ extern struct omap_hwmod_class omap2xxx_dma_hwmod_class;
 extern struct omap_hwmod_class omap2xxx_mailbox_hwmod_class;
 extern struct omap_hwmod_class omap2xxx_mcspi_class;
 
+extern struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr;
+
 #endif
index 6a66aa5..d15225f 100644 (file)
@@ -237,7 +237,7 @@ static int __devexit omap4_l3_remove(struct platform_device *pdev)
 static const struct of_device_id l3_noc_match[] = {
        {.compatible = "ti,omap4-l3-noc", },
        {},
-}
+};
 MODULE_DEVICE_TABLE(of, l3_noc_match);
 #else
 #define l3_noc_match NULL
index 1e79bdf..00bff46 100644 (file)
@@ -24,6 +24,7 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "pm.h"
+#include "twl-common.h"
 
 static struct omap_device_pm_latency *pm_lats;
 
@@ -226,11 +227,8 @@ postcore_initcall(omap2_common_pm_init);
 
 static int __init omap2_common_pm_late_init(void)
 {
-       /* Init the OMAP TWL parameters */
-       omap3_twl_init();
-       omap4_twl_init();
-
        /* Init the voltage layer */
+       omap_pmic_late_init();
        omap_voltage_late_init();
 
        /* Initialize the voltages */
index 6a4f683..cf246b3 100644 (file)
@@ -139,7 +139,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
                sr_write_reg(sr_info, ERRCONFIG_V1, status);
        } else if (sr_info->ip_type == SR_TYPE_V2) {
                /* Read the status bits */
-               sr_read_reg(sr_info, IRQSTATUS);
+               status = sr_read_reg(sr_info, IRQSTATUS);
 
                /* Clear them by writing back */
                sr_write_reg(sr_info, IRQSTATUS, status);
index 5224357..10b20c6 100644 (file)
@@ -30,6 +30,7 @@
 #include <plat/usb.h>
 
 #include "twl-common.h"
+#include "pm.h"
 
 static struct i2c_board_info __initdata pmic_i2c_board_info = {
        .addr           = 0x48,
@@ -48,6 +49,16 @@ void __init omap_pmic_init(int bus, u32 clkrate,
        omap_register_i2c_bus(bus, clkrate, &pmic_i2c_board_info, 1);
 }
 
+void __init omap_pmic_late_init(void)
+{
+       /* Init the OMAP TWL parameters (if PMIC has been registerd) */
+       if (!pmic_i2c_board_info.irq)
+               return;
+
+       omap3_twl_init();
+       omap4_twl_init();
+}
+
 #if defined(CONFIG_ARCH_OMAP3)
 static struct twl4030_usb_data omap3_usb_pdata = {
        .usb_mode       = T2_USB_MODE_ULPI,
index 5e83a5b..275dde8 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __OMAP_PMIC_COMMON__
 #define __OMAP_PMIC_COMMON__
 
+#include <plat/irqs.h>
+
 #define TWL_COMMON_PDATA_USB           (1 << 0)
 #define TWL_COMMON_PDATA_BCI           (1 << 1)
 #define TWL_COMMON_PDATA_MADC          (1 << 2)
@@ -30,6 +32,7 @@ struct twl4030_platform_data;
 
 void omap_pmic_init(int bus, u32 clkrate, const char *pmic_type, int pmic_irq,
                    struct twl4030_platform_data *pmic_data);
+void omap_pmic_late_init(void);
 
 static inline void omap2_pmic_init(const char *pmic_type,
                                   struct twl4030_platform_data *pmic_data)
index 8f2c234..58d4ee3 100644 (file)
@@ -14,7 +14,7 @@
 
 #define UART_SHIFT 2
 
-               .macro  addruart, rp, rv
+               .macro  addruart, rp, rv, tmp
                ldr     \rv, =PHYS_TO_IO(PICOXCELL_UART1_BASE)
                ldr     \rp, =PICOXCELL_UART1_BASE
                .endm
index fc0b854..4b81f59 100644 (file)
@@ -307,7 +307,7 @@ static inline void balloon3_mmc_init(void) {}
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static void balloon3_udc_command(int cmd)
 {
        if (cmd == PXA2XX_UDC_CMD_CONNECT)
index 692e1ff..d23b92b 100644 (file)
@@ -146,7 +146,7 @@ static void __init colibri_pxa320_init_eth(void)
 static inline void __init colibri_pxa320_init_eth(void) {}
 #endif /* CONFIG_AX88796 */
 
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info colibri_pxa320_gpio_vbus_info = {
        .gpio_vbus              = mfp_to_gpio(MFP_PIN_GPIO96),
        .gpio_pullup            = -1,
index 9c8208c..ffdd70d 100644 (file)
@@ -106,7 +106,7 @@ static void __init gumstix_mmc_init(void)
 }
 #endif
 
-#ifdef CONFIG_USB_GADGET_PXA25X
+#ifdef CONFIG_USB_PXA25X
 static struct gpio_vbus_mach_info gumstix_udc_info = {
        .gpio_vbus              = GPIO_GUMSTIX_USB_GPIOn,
        .gpio_pullup            = GPIO_GUMSTIX_USB_GPIOx,
index f80bbe2..d4eac3d 100644 (file)
@@ -37,8 +37,8 @@ extern void __init palm27x_lcd_init(int power,
 #define palm27x_lcd_init(power, mode)  do {} while (0)
 #endif
 
-#if    defined(CONFIG_USB_GADGET_PXA27X) || \
-       defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if    defined(CONFIG_USB_PXA27X) || \
+       defined(CONFIG_USB_PXA27X_MODULE)
 extern void __init palm27x_udc_init(int vbus, int pullup,
                                        int vbus_inverted);
 #else
index 325c245..fbc10d7 100644 (file)
@@ -164,8 +164,8 @@ void __init palm27x_lcd_init(int power, struct pxafb_mode_info *mode)
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if    defined(CONFIG_USB_GADGET_PXA27X) || \
-       defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if    defined(CONFIG_USB_PXA27X) || \
+       defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info palm27x_udc_info = {
        .gpio_vbus_inverted     = 1,
 };
index 6ec7cae..2c24c67 100644 (file)
@@ -338,7 +338,7 @@ static inline void palmtc_mkp_init(void) {}
 /******************************************************************************
  * UDC
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA25X)||defined(CONFIG_USB_GADGET_PXA25X_MODULE)
+#if defined(CONFIG_USB_PXA25X)||defined(CONFIG_USB_PXA25X_MODULE)
 static struct gpio_vbus_mach_info palmtc_udc_info = {
        .gpio_vbus              = GPIO_NR_PALMTC_USB_DETECT_N,
        .gpio_vbus_inverted     = 1,
index a7539a6..ca0c661 100644 (file)
@@ -343,7 +343,7 @@ static inline void vpac270_uhc_init(void) {}
 /******************************************************************************
  * USB Gadget
  ******************************************************************************/
-#if defined(CONFIG_USB_GADGET_PXA27X)||defined(CONFIG_USB_GADGET_PXA27X_MODULE)
+#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
 static struct gpio_vbus_mach_info vpac270_gpio_vbus_info = {
        .gpio_vbus              = GPIO41_VPAC270_UDC_DETECT,
        .gpio_pullup            = -1,
index 6666856..f208154 100644 (file)
@@ -8,7 +8,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
 
index 2aec2f7..737bdc6 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 # Common objects
-obj-y                          := timer.o console.o clock.o pm_runtime.o
+obj-y                          := timer.o console.o clock.o
 
 # CPU objects
 obj-$(CONFIG_ARCH_SH7367)      += setup-sh7367.o clock-sh7367.o intc-sh7367.o
index 83624e2..b862e9f 100644 (file)
@@ -515,14 +515,14 @@ static void __init ag5evm_init(void)
        /* enable MMCIF */
        gpio_request(GPIO_FN_MMCCLK0, NULL);
        gpio_request(GPIO_FN_MMCCMD0_PU, NULL);
-       gpio_request(GPIO_FN_MMCD0_0, NULL);
-       gpio_request(GPIO_FN_MMCD0_1, NULL);
-       gpio_request(GPIO_FN_MMCD0_2, NULL);
-       gpio_request(GPIO_FN_MMCD0_3, NULL);
-       gpio_request(GPIO_FN_MMCD0_4, NULL);
-       gpio_request(GPIO_FN_MMCD0_5, NULL);
-       gpio_request(GPIO_FN_MMCD0_6, NULL);
-       gpio_request(GPIO_FN_MMCD0_7, NULL);
+       gpio_request(GPIO_FN_MMCD0_0_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_1_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_2_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_3_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_4_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_5_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_6_PU, NULL);
+       gpio_request(GPIO_FN_MMCD0_7_PU, NULL);
        gpio_request(GPIO_PORT208, NULL); /* Reset */
        gpio_direction_output(GPIO_PORT208, 1);
 
index a3aa0f6..4c865ec 100644 (file)
@@ -201,7 +201,7 @@ static struct physmap_flash_data nor_flash_data = {
 static struct resource nor_flash_resources[] = {
        [0]     = {
                .start  = 0x20000000, /* CS0 shadow instead of regular CS0 */
-               .end    = 0x28000000 - 1, /* needed by USB MASK ROM boot */             
+               .end    = 0x28000000 - 1, /* needed by USB MASK ROM boot */
                .flags  = IORESOURCE_MEM,
        }
 };
index adc7312..bd9a784 100644 (file)
@@ -48,6 +48,7 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/traps.h>
 
+/* SMSC 9220 */
 static struct resource smsc9220_resources[] = {
        [0] = {
                .start          = 0x14000000, /* CS5A */
@@ -77,6 +78,7 @@ static struct platform_device eth_device = {
        .num_resources  = ARRAY_SIZE(smsc9220_resources),
 };
 
+/* KEYSC */
 static struct sh_keysc_info keysc_platdata = {
        .mode           = SH_KEYSC_MODE_6,
        .scan_timing    = 3,
@@ -120,6 +122,7 @@ static struct platform_device keysc_device = {
        },
 };
 
+/* GPIO KEY */
 #define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
 
 static struct gpio_keys_button gpio_buttons[] = {
@@ -150,6 +153,7 @@ static struct platform_device gpio_keys_device = {
        },
 };
 
+/* GPIO LED */
 #define GPIO_LED(n, g) { .name = n, .gpio = g }
 
 static struct gpio_led gpio_leds[] = {
@@ -175,6 +179,7 @@ static struct platform_device gpio_leds_device = {
        },
 };
 
+/* MMCIF */
 static struct resource mmcif_resources[] = {
        [0] = {
                .name   = "MMCIF",
@@ -207,6 +212,7 @@ static struct platform_device mmcif_device = {
        .resource       = mmcif_resources,
 };
 
+/* SDHI0 */
 static struct sh_mobile_sdhi_info sdhi0_info = {
        .tmio_caps      = MMC_CAP_SD_HIGHSPEED,
        .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
@@ -243,6 +249,7 @@ static struct platform_device sdhi0_device = {
        },
 };
 
+/* SDHI1 */
 static struct sh_mobile_sdhi_info sdhi1_info = {
        .tmio_caps      = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
        .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE | TMIO_MMC_HAS_IDLE_WAIT,
index 6697592..995a9c3 100644 (file)
@@ -476,7 +476,7 @@ static struct clk_ops fsidiv_clk_ops = {
        .disable        = fsidiv_disable,
 };
 
-static struct clk_mapping sh7372_fsidiva_clk_mapping = {
+static struct clk_mapping fsidiva_clk_mapping = {
        .phys   = FSIDIVA,
        .len    = 8,
 };
@@ -484,10 +484,10 @@ static struct clk_mapping sh7372_fsidiva_clk_mapping = {
 struct clk sh7372_fsidiva_clk = {
        .ops            = &fsidiv_clk_ops,
        .parent         = &div6_reparent_clks[DIV6_FSIA], /* late install */
-       .mapping        = &sh7372_fsidiva_clk_mapping,
+       .mapping        = &fsidiva_clk_mapping,
 };
 
-static struct clk_mapping sh7372_fsidivb_clk_mapping = {
+static struct clk_mapping fsidivb_clk_mapping = {
        .phys   = FSIDIVB,
        .len    = 8,
 };
@@ -495,7 +495,7 @@ static struct clk_mapping sh7372_fsidivb_clk_mapping = {
 struct clk sh7372_fsidivb_clk = {
        .ops            = &fsidiv_clk_ops,
        .parent         = &div6_reparent_clks[DIV6_FSIB],  /* late install */
-       .mapping        = &sh7372_fsidivb_clk_mapping,
+       .mapping        = &fsidivb_clk_mapping,
 };
 
 static struct clk *late_main_clks[] = {
index 2e44f11..1b23342 100644 (file)
@@ -26,65 +26,59 @@ void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = {
 };
 
 static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
-                                 struct cpuidle_state *state)
+                                 struct cpuidle_driver *drv,
+                                 int index)
 {
        ktime_t before, after;
-       int requested_state = state - &dev->states[0];
 
-       dev->last_state = &dev->states[requested_state];
        before = ktime_get();
 
        local_irq_disable();
        local_fiq_disable();
 
-       shmobile_cpuidle_modes[requested_state]();
+       shmobile_cpuidle_modes[index]();
 
        local_irq_enable();
        local_fiq_enable();
 
        after = ktime_get();
-       return ktime_to_ns(ktime_sub(after, before)) >> 10;
+       dev->last_residency = ktime_to_ns(ktime_sub(after, before)) >> 10;
+
+       return index;
 }
 
 static struct cpuidle_device shmobile_cpuidle_dev;
 static struct cpuidle_driver shmobile_cpuidle_driver = {
        .name =         "shmobile_cpuidle",
        .owner =        THIS_MODULE,
+       .states[0] = {
+               .name = "C1",
+               .desc = "WFI",
+               .exit_latency = 1,
+               .target_residency = 1 * 2,
+               .flags = CPUIDLE_FLAG_TIME_VALID,
+       },
+       .safe_state_index = 0, /* C1 */
+       .state_count = 1,
 };
 
-void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
+void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
 
 static int shmobile_cpuidle_init(void)
 {
        struct cpuidle_device *dev = &shmobile_cpuidle_dev;
-       struct cpuidle_state *state;
+       struct cpuidle_driver *drv = &shmobile_cpuidle_driver;
        int i;
 
-       cpuidle_register_driver(&shmobile_cpuidle_driver);
-
-       for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
-               dev->states[i].name[0] = '\0';
-               dev->states[i].desc[0] = '\0';
-               dev->states[i].enter = shmobile_cpuidle_enter;
-       }
-
-       i = CPUIDLE_DRIVER_STATE_START;
-
-       state = &dev->states[i++];
-       snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
-       strncpy(state->desc, "WFI", CPUIDLE_DESC_LEN);
-       state->exit_latency = 1;
-       state->target_residency = 1 * 2;
-       state->power_usage = 3;
-       state->flags = 0;
-       state->flags |= CPUIDLE_FLAG_TIME_VALID;
-
-       dev->safe_state = state;
-       dev->state_count = i;
+       for (i = 0; i < CPUIDLE_STATE_MAX; i++)
+               drv->states[i].enter = shmobile_cpuidle_enter;
 
        if (shmobile_cpuidle_setup)
-               shmobile_cpuidle_setup(dev);
+               shmobile_cpuidle_setup(drv);
+
+       cpuidle_register_driver(drv);
 
+       dev->state_count = drv->state_count;
        cpuidle_register_device(dev);
 
        return 0;
index c0cdbf9..834bd6c 100644 (file)
@@ -9,9 +9,9 @@ extern int clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
 extern void shmobile_handle_irq_gic(struct pt_regs *);
 extern struct platform_suspend_ops shmobile_suspend_ops;
-struct cpuidle_device;
+struct cpuidle_driver;
 extern void (*shmobile_cpuidle_modes[])(void);
-extern void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
+extern void (*shmobile_cpuidle_setup)(struct cpuidle_driver *drv);
 
 extern void sh7367_init_irq(void);
 extern void sh7367_add_early_devices(void);
index 18ae6a9..881d515 100644 (file)
@@ -470,6 +470,14 @@ enum {
        GPIO_FN_SDHICMD2_PU,
        GPIO_FN_MMCCMD0_PU,
        GPIO_FN_MMCCMD1_PU,
+       GPIO_FN_MMCD0_0_PU,
+       GPIO_FN_MMCD0_1_PU,
+       GPIO_FN_MMCD0_2_PU,
+       GPIO_FN_MMCD0_3_PU,
+       GPIO_FN_MMCD0_4_PU,
+       GPIO_FN_MMCD0_5_PU,
+       GPIO_FN_MMCD0_6_PU,
+       GPIO_FN_MMCD0_7_PU,
        GPIO_FN_FSIACK_PU,
        GPIO_FN_FSIAILR_PU,
        GPIO_FN_FSIAIBT_PU,
index 128555e..e6e5246 100644 (file)
 #include <linux/gpio.h>
 #include <mach/sh7367.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)                              \
-       _1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),       \
-       _1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),       \
-       _1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),       \
-       _1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),       \
-       _1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _90(fn, pfx, sfx)                              \
-       _10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),     \
-       _10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),     \
-       _10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),     \
-       _10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),     \
-       _10(fn, pfx##9, sfx)
-
-#define _273(fn, pfx, sfx)             \
-       _10(fn, pfx, sfx), _90(fn, pfx, sfx),           \
-       _10(fn, pfx##10, sfx), _90(fn, pfx##1, sfx),    \
-       _10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),   \
-       _10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),   \
-       _10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),   \
-       _10(fn, pfx##26, sfx), _1(fn, pfx##270, sfx),   \
-       _1(fn, pfx##271, sfx), _1(fn, pfx##272, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_273(str) _273(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)                             \
+       PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),           \
+       PORT_10(fn, pfx##10, sfx), PORT_90(fn, pfx##1, sfx),    \
+       PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),   \
+       PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),   \
+       PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),   \
+       PORT_10(fn, pfx##26, sfx), PORT_1(fn, pfx##270, sfx),   \
+       PORT_1(fn, pfx##271, sfx), PORT_1(fn, pfx##272, sfx)
 
 enum {
        PINMUX_RESERVED = 0,
 
        PINMUX_DATA_BEGIN,
-       PORT_273(DATA), /* PORT0_DATA -> PORT272_DATA */
+       PORT_ALL(DATA), /* PORT0_DATA -> PORT272_DATA */
        PINMUX_DATA_END,
 
        PINMUX_INPUT_BEGIN,
-       PORT_273(IN), /* PORT0_IN -> PORT272_IN */
+       PORT_ALL(IN), /* PORT0_IN -> PORT272_IN */
        PINMUX_INPUT_END,
 
        PINMUX_INPUT_PULLUP_BEGIN,
-       PORT_273(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
+       PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT272_IN_PU */
        PINMUX_INPUT_PULLUP_END,
 
        PINMUX_INPUT_PULLDOWN_BEGIN,
-       PORT_273(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
+       PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT272_IN_PD */
        PINMUX_INPUT_PULLDOWN_END,
 
        PINMUX_OUTPUT_BEGIN,
-       PORT_273(OUT), /* PORT0_OUT -> PORT272_OUT */
+       PORT_ALL(OUT), /* PORT0_OUT -> PORT272_OUT */
        PINMUX_OUTPUT_END,
 
        PINMUX_FUNCTION_BEGIN,
-       PORT_273(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
-       PORT_273(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
-       PORT_273(FN0), /* PORT0_FN0 -> PORT272_FN0 */
-       PORT_273(FN1), /* PORT0_FN1 -> PORT272_FN1 */
-       PORT_273(FN2), /* PORT0_FN2 -> PORT272_FN2 */
-       PORT_273(FN3), /* PORT0_FN3 -> PORT272_FN3 */
-       PORT_273(FN4), /* PORT0_FN4 -> PORT272_FN4 */
-       PORT_273(FN5), /* PORT0_FN5 -> PORT272_FN5 */
-       PORT_273(FN6), /* PORT0_FN6 -> PORT272_FN6 */
-       PORT_273(FN7), /* PORT0_FN7 -> PORT272_FN7 */
+       PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT272_FN_IN */
+       PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT272_FN_OUT */
+       PORT_ALL(FN0), /* PORT0_FN0 -> PORT272_FN0 */
+       PORT_ALL(FN1), /* PORT0_FN1 -> PORT272_FN1 */
+       PORT_ALL(FN2), /* PORT0_FN2 -> PORT272_FN2 */
+       PORT_ALL(FN3), /* PORT0_FN3 -> PORT272_FN3 */
+       PORT_ALL(FN4), /* PORT0_FN4 -> PORT272_FN4 */
+       PORT_ALL(FN5), /* PORT0_FN5 -> PORT272_FN5 */
+       PORT_ALL(FN6), /* PORT0_FN6 -> PORT272_FN6 */
+       PORT_ALL(FN7), /* PORT0_FN7 -> PORT272_FN7 */
 
        MSELBCR_MSEL2_1, MSELBCR_MSEL2_0,
        PINMUX_FUNCTION_END,
@@ -327,41 +308,6 @@ enum {
        PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-
 static pinmux_enum_t pinmux_data[] = {
 
        /* specify valid pin states for each pin in GPIO mode */
@@ -1098,13 +1044,9 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(DIVLOCK_MARK, PORT272_FN1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_273() _273(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
        /* 49-1 -> 49-6 (GPIO) */
-       GPIO_PORT_273(),
+       GPIO_PORT_ALL(),
 
        /* Special Pull-up / Pull-down Functions */
        GPIO_FN(PORT48_KEYIN0_PU), GPIO_FN(PORT49_KEYIN1_PU),
@@ -1345,22 +1287,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        GPIO_FN(DIVLOCK),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)            \
-       0, (out), (in), 0,                      \
-       0, 0, 0, 0,                             \
-       0, 0, (in_pd), 0,                       \
-       0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)                                                \
-       { PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {           \
-               PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,           \
-                    PORT##nr##_IN_PU, PORT##nr##_OUT),         \
-               PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2, \
-               PORT##nr##_FN3, PORT##nr##_FN4, PORT##nr##_FN5, \
-               PORT##nr##_FN6, PORT##nr##_FN7 }                \
-       }
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        PORTCR(0, 0xe6050000), /* PORT0CR */
        PORTCR(1, 0xe6050001), /* PORT1CR */
index 9c265da..1bd6585 100644 (file)
 #include <linux/gpio.h>
 #include <mach/sh7372.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)                              \
-       _1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),       \
-       _1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),       \
-       _1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),       \
-       _1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),       \
-       _1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _80(fn, pfx, sfx)                              \
-       _10(fn, pfx##1, sfx),   _10(fn, pfx##2, sfx),   \
-       _10(fn, pfx##3, sfx),   _10(fn, pfx##4, sfx),   \
-       _10(fn, pfx##5, sfx),   _10(fn, pfx##6, sfx),   \
-       _10(fn, pfx##7, sfx),   _10(fn, pfx##8, sfx)
-
-#define _190(fn, pfx, sfx) \
-       _10(fn, pfx, sfx), _80(fn, pfx, sfx), _10(fn, pfx##9, sfx), \
-       _10(fn, pfx##10, sfx), _80(fn, pfx##1, sfx), _1(fn, pfx##190, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_ALL(str) _190(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx) \
+       PORT_10(fn, pfx, sfx),          PORT_90(fn, pfx, sfx), \
+       PORT_10(fn, pfx##10, sfx),      PORT_10(fn, pfx##11, sfx), \
+       PORT_10(fn, pfx##12, sfx),      PORT_10(fn, pfx##13, sfx), \
+       PORT_10(fn, pfx##14, sfx),      PORT_10(fn, pfx##15, sfx), \
+       PORT_10(fn, pfx##16, sfx),      PORT_10(fn, pfx##17, sfx), \
+       PORT_10(fn, pfx##18, sfx),      PORT_1(fn, pfx##190, sfx)
 
 enum {
        PINMUX_RESERVED = 0,
@@ -381,108 +367,124 @@ enum {
        PINMUX_MARK_END,
 };
 
-/* PORT_DATA_I_PD(nr) */
-#define _I___D(nr)                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD)
-
-/* PORT_DATA_I_PU(nr) */
-#define _I__U_(nr)                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PU)
-
-/* PORT_DATA_I_PU_PD(nr) */
-#define _I__UD(nr)                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-/* PORT_DATA_O(nr) */
-#define __O___(nr)                                                     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
-
-/* PORT_DATA_IO(nr) */
-#define _IO___(nr)                                  \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN)
-
-/* PORT_DATA_IO_PD(nr) */
-#define _IO__D(nr)                                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD)
-
-/* PORT_DATA_IO_PU(nr) */
-#define _IO_U_(nr)                                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PU)
-
-/* PORT_DATA_IO_PU_PD(nr) */
-#define _IO_UD(nr)                                          \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT, \
-                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
-
 static pinmux_enum_t pinmux_data[] = {
 
        /* specify valid pin states for each pin in GPIO mode */
-
-       _IO__D(0), _IO__D(1), __O___(2), _I___D(3), _I___D(4),
-       _I___D(5), _IO_UD(6), _I___D(7), _IO__D(8), __O___(9),
-
-       __O___(10), __O___(11), _IO_UD(12), _IO__D(13), _IO__D(14),
-       __O___(15), _IO__D(16), _IO__D(17), _I___D(18), _IO___(19),
-
-       _IO___(20), _IO___(21), _IO___(22), _IO___(23), _IO___(24),
-       _IO___(25), _IO___(26), _IO___(27), _IO___(28), _IO___(29),
-
-       _IO___(30), _IO___(31), _IO___(32), _IO___(33), _IO___(34),
-       _IO___(35), _IO___(36), _IO___(37), _IO___(38), _IO___(39),
-
-       _IO___(40), _IO___(41), _IO___(42), _IO___(43), _IO___(44),
-       _IO___(45), _IO_U_(46), _IO_U_(47), _IO_U_(48), _IO_U_(49),
-
-       _IO_U_(50), _IO_U_(51), _IO_U_(52), _IO_U_(53), _IO_U_(54),
-       _IO_U_(55), _IO_U_(56), _IO_U_(57), _IO_U_(58), _IO_U_(59),
-
-       _IO_U_(60), _IO_U_(61), _IO___(62), __O___(63), __O___(64),
-       _IO_U_(65), __O___(66), _IO_U_(67), __O___(68), _IO___(69), /*66?*/
-
-       _IO___(70), _IO___(71), __O___(72), _I__U_(73), _I__UD(74),
-       _IO_UD(75), _IO_UD(76), _IO_UD(77), _IO_UD(78), _IO_UD(79),
-
-       _IO_UD(80), _IO_UD(81), _IO_UD(82), _IO_UD(83), _IO_UD(84),
-       _IO_UD(85), _IO_UD(86), _IO_UD(87), _IO_UD(88), _IO_UD(89),
-
-       _IO_UD(90), _IO_UD(91), _IO_UD(92), _IO_UD(93), _IO_UD(94),
-       _IO_UD(95), _IO_U_(96), _IO_UD(97), _IO_UD(98), __O___(99), /*99?*/
-
-       _IO__D(100), _IO__D(101), _IO__D(102), _IO__D(103), _IO__D(104),
-       _IO__D(105), _IO_U_(106), _IO_U_(107), _IO_U_(108), _IO_U_(109),
-
-       _IO_U_(110), _IO_U_(111), _IO__D(112), _IO__D(113), _IO_U_(114),
-       _IO_U_(115), _IO_U_(116), _IO_U_(117), _IO_U_(118), _IO_U_(119),
-
-       _IO_U_(120), _IO__D(121), _IO__D(122), _IO__D(123), _IO__D(124),
-       _IO__D(125), _IO__D(126), _IO__D(127), _IO__D(128), _IO_UD(129),
-
-       _IO_UD(130), _IO_UD(131), _IO_UD(132), _IO_UD(133), _IO_UD(134),
-       _IO_UD(135), _IO__D(136), _IO__D(137), _IO__D(138), _IO__D(139),
-
-       _IO__D(140), _IO__D(141), _IO__D(142), _IO_UD(143), _IO__D(144),
-       _IO__D(145), _IO__D(146), _IO__D(147), _IO__D(148), _IO__D(149),
-
-       _IO__D(150), _IO__D(151), _IO_UD(152), _I___D(153), _IO_UD(154),
-       _I___D(155), _IO__D(156), _IO__D(157), _I___D(158), _IO__D(159),
-
-       __O___(160), _IO__D(161), _IO__D(162), _IO__D(163), _I___D(164),
-       _IO__D(165), _I___D(166), _I___D(167), _I___D(168), _I___D(169),
-
-       _I___D(170), __O___(171), _IO_UD(172), _IO_UD(173), _IO_UD(174),
-       _IO_UD(175), _IO_UD(176), _IO_UD(177), _IO_UD(178), __O___(179),
-
-       _IO_UD(180), _IO_UD(181), _IO_UD(182), _IO_UD(183), _IO_UD(184),
-       __O___(185), _IO_UD(186), _IO_UD(187), _IO_UD(188), _IO_UD(189),
-
-       _IO_UD(190),
+       PORT_DATA_IO_PD(0),             PORT_DATA_IO_PD(1),
+       PORT_DATA_O(2),                 PORT_DATA_I_PD(3),
+       PORT_DATA_I_PD(4),              PORT_DATA_I_PD(5),
+       PORT_DATA_IO_PU_PD(6),          PORT_DATA_I_PD(7),
+       PORT_DATA_IO_PD(8),             PORT_DATA_O(9),
+
+       PORT_DATA_O(10),                PORT_DATA_O(11),
+       PORT_DATA_IO_PU_PD(12),         PORT_DATA_IO_PD(13),
+       PORT_DATA_IO_PD(14),            PORT_DATA_O(15),
+       PORT_DATA_IO_PD(16),            PORT_DATA_IO_PD(17),
+       PORT_DATA_I_PD(18),             PORT_DATA_IO(19),
+
+       PORT_DATA_IO(20),               PORT_DATA_IO(21),
+       PORT_DATA_IO(22),               PORT_DATA_IO(23),
+       PORT_DATA_IO(24),               PORT_DATA_IO(25),
+       PORT_DATA_IO(26),               PORT_DATA_IO(27),
+       PORT_DATA_IO(28),               PORT_DATA_IO(29),
+
+       PORT_DATA_IO(30),               PORT_DATA_IO(31),
+       PORT_DATA_IO(32),               PORT_DATA_IO(33),
+       PORT_DATA_IO(34),               PORT_DATA_IO(35),
+       PORT_DATA_IO(36),               PORT_DATA_IO(37),
+       PORT_DATA_IO(38),               PORT_DATA_IO(39),
+
+       PORT_DATA_IO(40),               PORT_DATA_IO(41),
+       PORT_DATA_IO(42),               PORT_DATA_IO(43),
+       PORT_DATA_IO(44),               PORT_DATA_IO(45),
+       PORT_DATA_IO_PU(46),            PORT_DATA_IO_PU(47),
+       PORT_DATA_IO_PU(48),            PORT_DATA_IO_PU(49),
+
+       PORT_DATA_IO_PU(50),            PORT_DATA_IO_PU(51),
+       PORT_DATA_IO_PU(52),            PORT_DATA_IO_PU(53),
+       PORT_DATA_IO_PU(54),            PORT_DATA_IO_PU(55),
+       PORT_DATA_IO_PU(56),            PORT_DATA_IO_PU(57),
+       PORT_DATA_IO_PU(58),            PORT_DATA_IO_PU(59),
+
+       PORT_DATA_IO_PU(60),            PORT_DATA_IO_PU(61),
+       PORT_DATA_IO(62),               PORT_DATA_O(63),
+       PORT_DATA_O(64),                PORT_DATA_IO_PU(65),
+       PORT_DATA_O(66),                PORT_DATA_IO_PU(67),  /*66?*/
+       PORT_DATA_O(68),                PORT_DATA_IO(69),
+
+       PORT_DATA_IO(70),               PORT_DATA_IO(71),
+       PORT_DATA_O(72),                PORT_DATA_I_PU(73),
+       PORT_DATA_I_PU_PD(74),          PORT_DATA_IO_PU_PD(75),
+       PORT_DATA_IO_PU_PD(76),         PORT_DATA_IO_PU_PD(77),
+       PORT_DATA_IO_PU_PD(78),         PORT_DATA_IO_PU_PD(79),
+
+       PORT_DATA_IO_PU_PD(80),         PORT_DATA_IO_PU_PD(81),
+       PORT_DATA_IO_PU_PD(82),         PORT_DATA_IO_PU_PD(83),
+       PORT_DATA_IO_PU_PD(84),         PORT_DATA_IO_PU_PD(85),
+       PORT_DATA_IO_PU_PD(86),         PORT_DATA_IO_PU_PD(87),
+       PORT_DATA_IO_PU_PD(88),         PORT_DATA_IO_PU_PD(89),
+
+       PORT_DATA_IO_PU_PD(90),         PORT_DATA_IO_PU_PD(91),
+       PORT_DATA_IO_PU_PD(92),         PORT_DATA_IO_PU_PD(93),
+       PORT_DATA_IO_PU_PD(94),         PORT_DATA_IO_PU_PD(95),
+       PORT_DATA_IO_PU(96),            PORT_DATA_IO_PU_PD(97),
+       PORT_DATA_IO_PU_PD(98),         PORT_DATA_O(99), /*99?*/
+
+       PORT_DATA_IO_PD(100),           PORT_DATA_IO_PD(101),
+       PORT_DATA_IO_PD(102),           PORT_DATA_IO_PD(103),
+       PORT_DATA_IO_PD(104),           PORT_DATA_IO_PD(105),
+       PORT_DATA_IO_PU(106),           PORT_DATA_IO_PU(107),
+       PORT_DATA_IO_PU(108),           PORT_DATA_IO_PU(109),
+
+       PORT_DATA_IO_PU(110),           PORT_DATA_IO_PU(111),
+       PORT_DATA_IO_PD(112),           PORT_DATA_IO_PD(113),
+       PORT_DATA_IO_PU(114),           PORT_DATA_IO_PU(115),
+       PORT_DATA_IO_PU(116),           PORT_DATA_IO_PU(117),
+       PORT_DATA_IO_PU(118),           PORT_DATA_IO_PU(119),
+
+       PORT_DATA_IO_PU(120),           PORT_DATA_IO_PD(121),
+       PORT_DATA_IO_PD(122),           PORT_DATA_IO_PD(123),
+       PORT_DATA_IO_PD(124),           PORT_DATA_IO_PD(125),
+       PORT_DATA_IO_PD(126),           PORT_DATA_IO_PD(127),
+       PORT_DATA_IO_PD(128),           PORT_DATA_IO_PU_PD(129),
+
+       PORT_DATA_IO_PU_PD(130),        PORT_DATA_IO_PU_PD(131),
+       PORT_DATA_IO_PU_PD(132),        PORT_DATA_IO_PU_PD(133),
+       PORT_DATA_IO_PU_PD(134),        PORT_DATA_IO_PU_PD(135),
+       PORT_DATA_IO_PD(136),           PORT_DATA_IO_PD(137),
+       PORT_DATA_IO_PD(138),           PORT_DATA_IO_PD(139),
+
+       PORT_DATA_IO_PD(140),           PORT_DATA_IO_PD(141),
+       PORT_DATA_IO_PD(142),           PORT_DATA_IO_PU_PD(143),
+       PORT_DATA_IO_PD(144),           PORT_DATA_IO_PD(145),
+       PORT_DATA_IO_PD(146),           PORT_DATA_IO_PD(147),
+       PORT_DATA_IO_PD(148),           PORT_DATA_IO_PD(149),
+
+       PORT_DATA_IO_PD(150),           PORT_DATA_IO_PD(151),
+       PORT_DATA_IO_PU_PD(152),        PORT_DATA_I_PD(153),
+       PORT_DATA_IO_PU_PD(154),        PORT_DATA_I_PD(155),
+       PORT_DATA_IO_PD(156),           PORT_DATA_IO_PD(157),
+       PORT_DATA_I_PD(158),            PORT_DATA_IO_PD(159),
+
+       PORT_DATA_O(160),               PORT_DATA_IO_PD(161),
+       PORT_DATA_IO_PD(162),           PORT_DATA_IO_PD(163),
+       PORT_DATA_I_PD(164),            PORT_DATA_IO_PD(165),
+       PORT_DATA_I_PD(166),            PORT_DATA_I_PD(167),
+       PORT_DATA_I_PD(168),            PORT_DATA_I_PD(169),
+
+       PORT_DATA_I_PD(170),            PORT_DATA_O(171),
+       PORT_DATA_IO_PU_PD(172),        PORT_DATA_IO_PU_PD(173),
+       PORT_DATA_IO_PU_PD(174),        PORT_DATA_IO_PU_PD(175),
+       PORT_DATA_IO_PU_PD(176),        PORT_DATA_IO_PU_PD(177),
+       PORT_DATA_IO_PU_PD(178),        PORT_DATA_O(179),
+
+       PORT_DATA_IO_PU_PD(180),        PORT_DATA_IO_PU_PD(181),
+       PORT_DATA_IO_PU_PD(182),        PORT_DATA_IO_PU_PD(183),
+       PORT_DATA_IO_PU_PD(184),        PORT_DATA_O(185),
+       PORT_DATA_IO_PU_PD(186),        PORT_DATA_IO_PU_PD(187),
+       PORT_DATA_IO_PU_PD(188),        PORT_DATA_IO_PU_PD(189),
+
+       PORT_DATA_IO_PU_PD(190),
 
        /* IRQ */
        PINMUX_DATA(IRQ0_6_MARK,        PORT6_FN0,      MSEL1CR_0_0),
@@ -926,10 +928,6 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(MFIv4_MARK,         MSEL4CR_6_1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_ALL() _190(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
 
        /* PORT */
@@ -1201,22 +1199,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        GPIO_FN(SDENC_DV_CLKI),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)            \
-       0, (out), (in), 0,                      \
-       0, 0, 0, 0,                             \
-       0, 0, (in_pd), 0,                       \
-       0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)                                                \
-       { PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {           \
-               PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,           \
-                    PORT##nr##_IN_PU, PORT##nr##_OUT),         \
-               PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2, \
-               PORT##nr##_FN3, PORT##nr##_FN4, PORT##nr##_FN5, \
-               PORT##nr##_FN6, PORT##nr##_FN7 }                \
-       }
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        PORTCR(0,       0xE6051000), /* PORT0CR */
        PORTCR(1,       0xE6051001), /* PORT1CR */
index 613e684..2f10511 100644 (file)
 #include <linux/gpio.h>
 #include <mach/sh7377.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)                              \
-       _1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),       \
-       _1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),       \
-       _1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),       \
-       _1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),       \
-       _1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _90(fn, pfx, sfx)                              \
-       _10(fn, pfx##1, sfx), _10(fn, pfx##2, sfx),     \
-       _10(fn, pfx##3, sfx), _10(fn, pfx##4, sfx),     \
-       _10(fn, pfx##5, sfx), _10(fn, pfx##6, sfx),     \
-       _10(fn, pfx##7, sfx), _10(fn, pfx##8, sfx),     \
-       _10(fn, pfx##9, sfx)
-
-#define _265(fn, pfx, sfx)                             \
-       _10(fn, pfx, sfx), _90(fn, pfx, sfx),           \
-       _10(fn, pfx##10, sfx),                          \
-       _1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),   \
-       _1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),   \
-       _1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),   \
-       _1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),   \
-       _1(fn, pfx##118, sfx),                          \
-       _1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),   \
-       _10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),   \
-       _10(fn, pfx##15, sfx),                          \
-       _1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),   \
-       _1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),   \
-       _1(fn, pfx##164, sfx),                          \
-       _1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),   \
-       _1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),   \
-       _1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),   \
-       _1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),   \
-       _10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),   \
-       _10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),   \
-       _10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),   \
-       _1(fn, pfx##260, sfx), _1(fn, pfx##261, sfx),   \
-       _1(fn, pfx##262, sfx), _1(fn, pfx##263, sfx),   \
-       _1(fn, pfx##264, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_265(str) _265(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)                             \
+       PORT_10(fn, pfx, sfx), PORT_90(fn, pfx, sfx),           \
+       PORT_10(fn, pfx##10, sfx),                              \
+       PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),   \
+       PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),   \
+       PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),   \
+       PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),   \
+       PORT_1(fn, pfx##118, sfx),                              \
+       PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),   \
+       PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),   \
+       PORT_10(fn, pfx##15, sfx),                              \
+       PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),   \
+       PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),   \
+       PORT_1(fn, pfx##164, sfx),                              \
+       PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),   \
+       PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),   \
+       PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),   \
+       PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),   \
+       PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),   \
+       PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),   \
+       PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),   \
+       PORT_1(fn, pfx##260, sfx), PORT_1(fn, pfx##261, sfx),   \
+       PORT_1(fn, pfx##262, sfx), PORT_1(fn, pfx##263, sfx),   \
+       PORT_1(fn, pfx##264, sfx)
 
 enum {
        PINMUX_RESERVED = 0,
 
        PINMUX_DATA_BEGIN,
-       PORT_265(DATA), /* PORT0_DATA -> PORT264_DATA */
+       PORT_ALL(DATA), /* PORT0_DATA -> PORT264_DATA */
        PINMUX_DATA_END,
 
        PINMUX_INPUT_BEGIN,
-       PORT_265(IN), /* PORT0_IN -> PORT264_IN */
+       PORT_ALL(IN), /* PORT0_IN -> PORT264_IN */
        PINMUX_INPUT_END,
 
        PINMUX_INPUT_PULLUP_BEGIN,
-       PORT_265(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
+       PORT_ALL(IN_PU), /* PORT0_IN_PU -> PORT264_IN_PU */
        PINMUX_INPUT_PULLUP_END,
 
        PINMUX_INPUT_PULLDOWN_BEGIN,
-       PORT_265(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
+       PORT_ALL(IN_PD), /* PORT0_IN_PD -> PORT264_IN_PD */
        PINMUX_INPUT_PULLDOWN_END,
 
        PINMUX_OUTPUT_BEGIN,
-       PORT_265(OUT), /* PORT0_OUT -> PORT264_OUT */
+       PORT_ALL(OUT), /* PORT0_OUT -> PORT264_OUT */
        PINMUX_OUTPUT_END,
 
        PINMUX_FUNCTION_BEGIN,
-       PORT_265(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
-       PORT_265(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
-       PORT_265(FN0), /* PORT0_FN0 -> PORT264_FN0 */
-       PORT_265(FN1), /* PORT0_FN1 -> PORT264_FN1 */
-       PORT_265(FN2), /* PORT0_FN2 -> PORT264_FN2 */
-       PORT_265(FN3), /* PORT0_FN3 -> PORT264_FN3 */
-       PORT_265(FN4), /* PORT0_FN4 -> PORT264_FN4 */
-       PORT_265(FN5), /* PORT0_FN5 -> PORT264_FN5 */
-       PORT_265(FN6), /* PORT0_FN6 -> PORT264_FN6 */
-       PORT_265(FN7), /* PORT0_FN7 -> PORT264_FN7 */
+       PORT_ALL(FN_IN), /* PORT0_FN_IN -> PORT264_FN_IN */
+       PORT_ALL(FN_OUT), /* PORT0_FN_OUT -> PORT264_FN_OUT */
+       PORT_ALL(FN0), /* PORT0_FN0 -> PORT264_FN0 */
+       PORT_ALL(FN1), /* PORT0_FN1 -> PORT264_FN1 */
+       PORT_ALL(FN2), /* PORT0_FN2 -> PORT264_FN2 */
+       PORT_ALL(FN3), /* PORT0_FN3 -> PORT264_FN3 */
+       PORT_ALL(FN4), /* PORT0_FN4 -> PORT264_FN4 */
+       PORT_ALL(FN5), /* PORT0_FN5 -> PORT264_FN5 */
+       PORT_ALL(FN6), /* PORT0_FN6 -> PORT264_FN6 */
+       PORT_ALL(FN7), /* PORT0_FN7 -> PORT264_FN7 */
 
        MSELBCR_MSEL17_1, MSELBCR_MSEL17_0,
        MSELBCR_MSEL16_1, MSELBCR_MSEL16_0,
@@ -360,45 +341,6 @@ enum {
        PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr)        \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)  \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PD,        \
-                               PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)        \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)       \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)    \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)    \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
 static pinmux_enum_t pinmux_data[] = {
        /* specify valid pin states for each pin in GPIO mode */
        /* 55-1 (GPIO) */
@@ -1078,13 +1020,9 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(RESETOUTS_MARK, PORT264_FN1),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_265() _265(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
        /* 55-1 -> 55-5 (GPIO) */
-       GPIO_PORT_265(),
+       GPIO_PORT_ALL(),
 
        /* Special Pull-up / Pull-down Functions */
        GPIO_FN(PORT66_KEYIN0_PU), GPIO_FN(PORT67_KEYIN1_PU),
@@ -1362,23 +1300,6 @@ static struct pinmux_gpio pinmux_gpios[] = {
        GPIO_FN(RESETOUTS),
 };
 
-/* helper for top 4 bits in PORTnCR */
-#define PCRH(in, in_pd, in_pu, out)    \
-       0, (out), (in), 0,      \
-               0, 0, 0, 0,     \
-               0, 0, (in_pd), 0,       \
-               0, 0, (in_pu), 0
-
-#define PORTCR(nr, reg)        \
-       { PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {   \
-                       PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,   \
-                                PORT##nr##_IN_PU, PORT##nr##_OUT),     \
-                               PORT##nr##_FN0, PORT##nr##_FN1, \
-                               PORT##nr##_FN2, PORT##nr##_FN3, \
-                               PORT##nr##_FN4, PORT##nr##_FN5, \
-                               PORT##nr##_FN6, PORT##nr##_FN7 }        \
-       }
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        PORTCR(0, 0xe6050000), /* PORT0CR */
        PORTCR(1, 0xe6050001), /* PORT1CR */
index 5abe02f..e05634c 100644 (file)
 #include <mach/sh73a0.h>
 #include <mach/irqs.h>
 
-#define _1(fn, pfx, sfx) fn(pfx, sfx)
-
-#define _10(fn, pfx, sfx)                              \
-       _1(fn, pfx##0, sfx), _1(fn, pfx##1, sfx),       \
-       _1(fn, pfx##2, sfx), _1(fn, pfx##3, sfx),       \
-       _1(fn, pfx##4, sfx), _1(fn, pfx##5, sfx),       \
-       _1(fn, pfx##6, sfx), _1(fn, pfx##7, sfx),       \
-       _1(fn, pfx##8, sfx), _1(fn, pfx##9, sfx)
-
-#define _310(fn, pfx, sfx)                             \
-       _10(fn, pfx,    sfx), _10(fn, pfx##1, sfx),     \
-       _10(fn, pfx##2, sfx), _10(fn, pfx##3, sfx),     \
-       _10(fn, pfx##4, sfx), _10(fn, pfx##5, sfx),     \
-       _10(fn, pfx##6, sfx), _10(fn, pfx##7, sfx),     \
-       _10(fn, pfx##8, sfx), _10(fn, pfx##9, sfx),     \
-       _10(fn, pfx##10, sfx),                          \
-       _1(fn, pfx##110, sfx), _1(fn, pfx##111, sfx),   \
-       _1(fn, pfx##112, sfx), _1(fn, pfx##113, sfx),   \
-       _1(fn, pfx##114, sfx), _1(fn, pfx##115, sfx),   \
-       _1(fn, pfx##116, sfx), _1(fn, pfx##117, sfx),   \
-       _1(fn, pfx##118, sfx),                          \
-       _1(fn, pfx##128, sfx), _1(fn, pfx##129, sfx),   \
-       _10(fn, pfx##13, sfx), _10(fn, pfx##14, sfx),   \
-       _10(fn, pfx##15, sfx),                          \
-       _1(fn, pfx##160, sfx), _1(fn, pfx##161, sfx),   \
-       _1(fn, pfx##162, sfx), _1(fn, pfx##163, sfx),   \
-       _1(fn, pfx##164, sfx),                          \
-       _1(fn, pfx##192, sfx), _1(fn, pfx##193, sfx),   \
-       _1(fn, pfx##194, sfx), _1(fn, pfx##195, sfx),   \
-       _1(fn, pfx##196, sfx), _1(fn, pfx##197, sfx),   \
-       _1(fn, pfx##198, sfx), _1(fn, pfx##199, sfx),   \
-       _10(fn, pfx##20, sfx), _10(fn, pfx##21, sfx),   \
-       _10(fn, pfx##22, sfx), _10(fn, pfx##23, sfx),   \
-       _10(fn, pfx##24, sfx), _10(fn, pfx##25, sfx),   \
-       _10(fn, pfx##26, sfx), _10(fn, pfx##27, sfx),   \
-       _1(fn, pfx##280, sfx), _1(fn, pfx##281, sfx),   \
-       _1(fn, pfx##282, sfx),                          \
-       _1(fn, pfx##288, sfx), _1(fn, pfx##289, sfx),   \
-       _10(fn, pfx##29, sfx), _10(fn, pfx##30, sfx)
-
-#define _PORT(pfx, sfx) pfx##_##sfx
-#define PORT_310(str) _310(_PORT, PORT, str)
+#define CPU_ALL_PORT(fn, pfx, sfx)                             \
+       PORT_10(fn, pfx,    sfx), PORT_10(fn, pfx##1, sfx),     \
+       PORT_10(fn, pfx##2, sfx), PORT_10(fn, pfx##3, sfx),     \
+       PORT_10(fn, pfx##4, sfx), PORT_10(fn, pfx##5, sfx),     \
+       PORT_10(fn, pfx##6, sfx), PORT_10(fn, pfx##7, sfx),     \
+       PORT_10(fn, pfx##8, sfx), PORT_10(fn, pfx##9, sfx),     \
+       PORT_10(fn, pfx##10, sfx),                              \
+       PORT_1(fn, pfx##110, sfx), PORT_1(fn, pfx##111, sfx),   \
+       PORT_1(fn, pfx##112, sfx), PORT_1(fn, pfx##113, sfx),   \
+       PORT_1(fn, pfx##114, sfx), PORT_1(fn, pfx##115, sfx),   \
+       PORT_1(fn, pfx##116, sfx), PORT_1(fn, pfx##117, sfx),   \
+       PORT_1(fn, pfx##118, sfx),                              \
+       PORT_1(fn, pfx##128, sfx), PORT_1(fn, pfx##129, sfx),   \
+       PORT_10(fn, pfx##13, sfx), PORT_10(fn, pfx##14, sfx),   \
+       PORT_10(fn, pfx##15, sfx),                              \
+       PORT_1(fn, pfx##160, sfx), PORT_1(fn, pfx##161, sfx),   \
+       PORT_1(fn, pfx##162, sfx), PORT_1(fn, pfx##163, sfx),   \
+       PORT_1(fn, pfx##164, sfx),                              \
+       PORT_1(fn, pfx##192, sfx), PORT_1(fn, pfx##193, sfx),   \
+       PORT_1(fn, pfx##194, sfx), PORT_1(fn, pfx##195, sfx),   \
+       PORT_1(fn, pfx##196, sfx), PORT_1(fn, pfx##197, sfx),   \
+       PORT_1(fn, pfx##198, sfx), PORT_1(fn, pfx##199, sfx),   \
+       PORT_10(fn, pfx##20, sfx), PORT_10(fn, pfx##21, sfx),   \
+       PORT_10(fn, pfx##22, sfx), PORT_10(fn, pfx##23, sfx),   \
+       PORT_10(fn, pfx##24, sfx), PORT_10(fn, pfx##25, sfx),   \
+       PORT_10(fn, pfx##26, sfx), PORT_10(fn, pfx##27, sfx),   \
+       PORT_1(fn, pfx##280, sfx), PORT_1(fn, pfx##281, sfx),   \
+       PORT_1(fn, pfx##282, sfx),                              \
+       PORT_1(fn, pfx##288, sfx), PORT_1(fn, pfx##289, sfx),   \
+       PORT_10(fn, pfx##29, sfx), PORT_10(fn, pfx##30, sfx)
 
 enum {
        PINMUX_RESERVED = 0,
 
        PINMUX_DATA_BEGIN,
-       PORT_310(DATA),                 /* PORT0_DATA -> PORT309_DATA */
+       PORT_ALL(DATA),                 /* PORT0_DATA -> PORT309_DATA */
        PINMUX_DATA_END,
 
        PINMUX_INPUT_BEGIN,
-       PORT_310(IN),                   /* PORT0_IN -> PORT309_IN */
+       PORT_ALL(IN),                   /* PORT0_IN -> PORT309_IN */
        PINMUX_INPUT_END,
 
        PINMUX_INPUT_PULLUP_BEGIN,
-       PORT_310(IN_PU),                /* PORT0_IN_PU -> PORT309_IN_PU */
+       PORT_ALL(IN_PU),                /* PORT0_IN_PU -> PORT309_IN_PU */
        PINMUX_INPUT_PULLUP_END,
 
        PINMUX_INPUT_PULLDOWN_BEGIN,
-       PORT_310(IN_PD),                /* PORT0_IN_PD -> PORT309_IN_PD */
+       PORT_ALL(IN_PD),                /* PORT0_IN_PD -> PORT309_IN_PD */
        PINMUX_INPUT_PULLDOWN_END,
 
        PINMUX_OUTPUT_BEGIN,
-       PORT_310(OUT),                  /* PORT0_OUT -> PORT309_OUT */
+       PORT_ALL(OUT),                  /* PORT0_OUT -> PORT309_OUT */
        PINMUX_OUTPUT_END,
 
        PINMUX_FUNCTION_BEGIN,
-       PORT_310(FN_IN),                /* PORT0_FN_IN -> PORT309_FN_IN */
-       PORT_310(FN_OUT),               /* PORT0_FN_OUT -> PORT309_FN_OUT */
-       PORT_310(FN0),                  /* PORT0_FN0 -> PORT309_FN0 */
-       PORT_310(FN1),                  /* PORT0_FN1 -> PORT309_FN1 */
-       PORT_310(FN2),                  /* PORT0_FN2 -> PORT309_FN2 */
-       PORT_310(FN3),                  /* PORT0_FN3 -> PORT309_FN3 */
-       PORT_310(FN4),                  /* PORT0_FN4 -> PORT309_FN4 */
-       PORT_310(FN5),                  /* PORT0_FN5 -> PORT309_FN5 */
-       PORT_310(FN6),                  /* PORT0_FN6 -> PORT309_FN6 */
-       PORT_310(FN7),                  /* PORT0_FN7 -> PORT309_FN7 */
+       PORT_ALL(FN_IN),                /* PORT0_FN_IN -> PORT309_FN_IN */
+       PORT_ALL(FN_OUT),               /* PORT0_FN_OUT -> PORT309_FN_OUT */
+       PORT_ALL(FN0),                  /* PORT0_FN0 -> PORT309_FN0 */
+       PORT_ALL(FN1),                  /* PORT0_FN1 -> PORT309_FN1 */
+       PORT_ALL(FN2),                  /* PORT0_FN2 -> PORT309_FN2 */
+       PORT_ALL(FN3),                  /* PORT0_FN3 -> PORT309_FN3 */
+       PORT_ALL(FN4),                  /* PORT0_FN4 -> PORT309_FN4 */
+       PORT_ALL(FN5),                  /* PORT0_FN5 -> PORT309_FN5 */
+       PORT_ALL(FN6),                  /* PORT0_FN6 -> PORT309_FN6 */
+       PORT_ALL(FN7),                  /* PORT0_FN7 -> PORT309_FN7 */
 
        MSEL2CR_MSEL19_0, MSEL2CR_MSEL19_1,
        MSEL2CR_MSEL18_0, MSEL2CR_MSEL18_1,
@@ -508,6 +496,14 @@ enum {
        SDHICMD2_PU_MARK,
        MMCCMD0_PU_MARK,
        MMCCMD1_PU_MARK,
+       MMCD0_0_PU_MARK,
+       MMCD0_1_PU_MARK,
+       MMCD0_2_PU_MARK,
+       MMCD0_3_PU_MARK,
+       MMCD0_4_PU_MARK,
+       MMCD0_5_PU_MARK,
+       MMCD0_6_PU_MARK,
+       MMCD0_7_PU_MARK,
        FSIBISLD_PU_MARK,
        FSIACK_PU_MARK,
        FSIAILR_PU_MARK,
@@ -517,45 +513,6 @@ enum {
        PINMUX_MARK_END,
 };
 
-#define PORT_DATA_I(nr)        \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
-
-#define PORT_DATA_I_PD(nr)     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PD)
-
-#define PORT_DATA_I_PU(nr)     \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PU)
-
-#define PORT_DATA_I_PU_PD(nr)  \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_IN, PORT##nr##_IN_PD,        \
-                               PORT##nr##_IN_PU)
-
-#define PORT_DATA_O(nr)        \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT)
-
-#define PORT_DATA_IO(nr)       \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN)
-
-#define PORT_DATA_IO_PD(nr)    \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PD)
-
-#define PORT_DATA_IO_PU(nr)    \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PU)
-
-#define PORT_DATA_IO_PU_PD(nr) \
-       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
-                               PORT##nr##_OUT, PORT##nr##_IN,          \
-                               PORT##nr##_IN_PD, PORT##nr##_IN_PU)
-
 static pinmux_enum_t pinmux_data[] = {
        /* specify valid pin states for each pin in GPIO mode */
 
@@ -1561,6 +1518,24 @@ static pinmux_enum_t pinmux_data[] = {
                MSEL4CR_MSEL15_0),
        PINMUX_DATA(MMCCMD1_PU_MARK, PORT297_FN2, PORT297_IN_PU,
                MSEL4CR_MSEL15_1),
+
+       PINMUX_DATA(MMCD0_0_PU_MARK,
+                   PORT271_FN1, PORT271_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_1_PU_MARK,
+                   PORT272_FN1, PORT272_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_2_PU_MARK,
+                   PORT273_FN1, PORT273_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_3_PU_MARK,
+                   PORT274_FN1, PORT274_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_4_PU_MARK,
+                   PORT275_FN1, PORT275_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_5_PU_MARK,
+                   PORT276_FN1, PORT276_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_6_PU_MARK,
+                   PORT277_FN1, PORT277_IN_PU, MSEL4CR_MSEL15_0),
+       PINMUX_DATA(MMCD0_7_PU_MARK,
+                   PORT278_FN1, PORT278_IN_PU, MSEL4CR_MSEL15_0),
+
        PINMUX_DATA(FSIBISLD_PU_MARK, PORT39_FN1, PORT39_IN_PU),
        PINMUX_DATA(FSIACK_PU_MARK, PORT49_FN1, PORT49_IN_PU),
        PINMUX_DATA(FSIAILR_PU_MARK, PORT50_FN5, PORT50_IN_PU),
@@ -1568,12 +1543,8 @@ static pinmux_enum_t pinmux_data[] = {
        PINMUX_DATA(FSIAISLD_PU_MARK, PORT55_FN1, PORT55_IN_PU),
 };
 
-#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
-#define GPIO_PORT_310() _310(_GPIO_PORT, , unused)
-#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
-
 static struct pinmux_gpio pinmux_gpios[] = {
-       GPIO_PORT_310(),
+       GPIO_PORT_ALL(),
 
        /* Table 25-1 (Functions 0-7) */
        GPIO_FN(VBUS_0),
@@ -2236,24 +2207,20 @@ static struct pinmux_gpio pinmux_gpios[] = {
        GPIO_FN(SDHICMD2_PU),
        GPIO_FN(MMCCMD0_PU),
        GPIO_FN(MMCCMD1_PU),
+       GPIO_FN(MMCD0_0_PU),
+       GPIO_FN(MMCD0_1_PU),
+       GPIO_FN(MMCD0_2_PU),
+       GPIO_FN(MMCD0_3_PU),
+       GPIO_FN(MMCD0_4_PU),
+       GPIO_FN(MMCD0_5_PU),
+       GPIO_FN(MMCD0_6_PU),
+       GPIO_FN(MMCD0_7_PU),
        GPIO_FN(FSIACK_PU),
        GPIO_FN(FSIAILR_PU),
        GPIO_FN(FSIAIBT_PU),
        GPIO_FN(FSIAISLD_PU),
 };
 
-#define PORTCR(nr, reg)        \
-       { PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) { \
-               0, \
-               /*0001*/ PORT##nr##_OUT , \
-               /*0010*/ PORT##nr##_IN , 0, 0, 0, 0, 0, 0, 0, \
-               /*1010*/ PORT##nr##_IN_PD, 0, 0, 0, \
-               /*1110*/ PORT##nr##_IN_PU, 0, \
-               PORT##nr##_FN0, PORT##nr##_FN1, PORT##nr##_FN2, \
-               PORT##nr##_FN3, PORT##nr##_FN4, PORT##nr##_FN5, \
-               PORT##nr##_FN6, PORT##nr##_FN7, 0, 0, 0, 0, 0, 0, 0, 0 } \
-       }
-
 static struct pinmux_cfg_reg pinmux_config_regs[] = {
        PORTCR(0, 0xe6050000), /* PORT0CR */
        PORTCR(1, 0xe6050001), /* PORT1CR */
index 7961273..34bbcbf 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/irq.h>
 #include <linux/bitrev.h>
+#include <linux/console.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/tlbflush.h>
@@ -106,9 +107,8 @@ static int pd_power_down(struct generic_pm_domain *genpd)
        return 0;
 }
 
-static int pd_power_up(struct generic_pm_domain *genpd)
+static int __pd_power_up(struct sh7372_pm_domain *sh7372_pd, bool do_resume)
 {
-       struct sh7372_pm_domain *sh7372_pd = to_sh7372_pd(genpd);
        unsigned int mask = 1 << sh7372_pd->bit_shift;
        unsigned int retry_count;
        int ret = 0;
@@ -123,13 +123,13 @@ static int pd_power_up(struct generic_pm_domain *genpd)
 
        for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
                if (!(__raw_readl(SWUCR) & mask))
-                       goto out;
+                       break;
                if (retry_count > PSTR_RETRIES)
                        udelay(PSTR_DELAY_US);
                else
                        cpu_relax();
        }
-       if (__raw_readl(SWUCR) & mask)
+       if (!retry_count)
                ret = -EIO;
 
        if (!sh7372_pd->no_debug)
@@ -137,12 +137,17 @@ static int pd_power_up(struct generic_pm_domain *genpd)
                         mask, __raw_readl(PSTR));
 
  out:
-       if (ret == 0 && sh7372_pd->resume)
+       if (ret == 0 && sh7372_pd->resume && do_resume)
                sh7372_pd->resume();
 
        return ret;
 }
 
+static int pd_power_up(struct generic_pm_domain *genpd)
+{
+        return __pd_power_up(to_sh7372_pd(genpd), true);
+}
+
 static void sh7372_a4r_suspend(void)
 {
        sh7372_intcs_suspend();
@@ -174,7 +179,7 @@ void sh7372_init_pm_domain(struct sh7372_pm_domain *sh7372_pd)
        genpd->active_wakeup = pd_active_wakeup;
        genpd->power_off = pd_power_down;
        genpd->power_on = pd_power_up;
-       genpd->power_on(&sh7372_pd->genpd);
+       __pd_power_up(sh7372_pd, false);
 }
 
 void sh7372_add_device_to_domain(struct sh7372_pm_domain *sh7372_pd,
@@ -227,11 +232,23 @@ struct sh7372_pm_domain sh7372_a3sp = {
        .no_debug = true,
 };
 
+static void sh7372_a3sp_init(void)
+{
+       /* serial consoles make use of SCIF hardware located in A3SP,
+        * keep such power domain on if "no_console_suspend" is set.
+        */
+       sh7372_a3sp.stay_on = !console_suspend_enabled;
+}
+
 struct sh7372_pm_domain sh7372_a3sg = {
        .bit_shift = 13,
 };
 
-#endif /* CONFIG_PM */
+#else /* !CONFIG_PM */
+
+static inline void sh7372_a3sp_init(void) {}
+
+#endif /* !CONFIG_PM */
 
 #if defined(CONFIG_SUSPEND) || defined(CONFIG_CPU_IDLE)
 static int sh7372_do_idle_core_standby(unsigned long unused)
@@ -402,22 +419,18 @@ static void sh7372_setup_a3sm(unsigned long msk, unsigned long msk2)
 
 #ifdef CONFIG_CPU_IDLE
 
-static void sh7372_cpuidle_setup(struct cpuidle_device *dev)
+static void sh7372_cpuidle_setup(struct cpuidle_driver *drv)
 {
-       struct cpuidle_state *state;
-       int i = dev->state_count;
+       struct cpuidle_state *state = &drv->states[drv->state_count];
 
-       state = &dev->states[i];
        snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
        strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
        state->exit_latency = 10;
        state->target_residency = 20 + 10;
-       state->power_usage = 1; /* perhaps not */
-       state->flags = 0;
-       state->flags |= CPUIDLE_FLAG_TIME_VALID;
-       shmobile_cpuidle_modes[i] = sh7372_enter_core_standby;
+       state->flags = CPUIDLE_FLAG_TIME_VALID;
+       shmobile_cpuidle_modes[drv->state_count] = sh7372_enter_core_standby;
 
-       dev->state_count = i + 1;
+       drv->state_count++;
 }
 
 static void sh7372_cpuidle_init(void)
@@ -469,6 +482,8 @@ void __init sh7372_pm_init(void)
        /* do not convert A3SM, A3SP, A3SG, A4R power down into A4S */
        __raw_writel(0, PDNSEL);
 
+       sh7372_a3sp_init();
+
        sh7372_suspend_init();
        sh7372_cpuidle_init();
 }
diff --git a/arch/arm/mach-shmobile/pm_runtime.c b/arch/arm/mach-shmobile/pm_runtime.c
deleted file mode 100644 (file)
index bd5c6a3..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * arch/arm/mach-shmobile/pm_runtime.c
- *
- * Runtime PM support code for SuperH Mobile ARM
- *
- *  Copyright (C) 2009-2010 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/pm_runtime.h>
-#include <linux/pm_domain.h>
-#include <linux/pm_clock.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/sh_clk.h>
-#include <linux/bitmap.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_PM_RUNTIME
-
-static int default_platform_runtime_idle(struct device *dev)
-{
-       /* suspend synchronously to disable clocks immediately */
-       return pm_runtime_suspend(dev);
-}
-
-static struct dev_pm_domain default_pm_domain = {
-       .ops = {
-               .runtime_suspend = pm_clk_suspend,
-               .runtime_resume = pm_clk_resume,
-               .runtime_idle = default_platform_runtime_idle,
-               USE_PLATFORM_PM_SLEEP_OPS
-       },
-};
-
-#define DEFAULT_PM_DOMAIN_PTR  (&default_pm_domain)
-
-#else
-
-#define DEFAULT_PM_DOMAIN_PTR  NULL
-
-#endif /* CONFIG_PM_RUNTIME */
-
-static struct pm_clk_notifier_block platform_bus_notifier = {
-       .pm_domain = DEFAULT_PM_DOMAIN_PTR,
-       .con_ids = { NULL, },
-};
-
-static int __init sh_pm_runtime_init(void)
-{
-       pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
-       return 0;
-}
-core_initcall(sh_pm_runtime_init);
-
-static int __init sh_pm_runtime_late_init(void)
-{
-       pm_genpd_poweroff_unused();
-       return 0;
-}
-late_initcall(sh_pm_runtime_late_init);
index d368f8d..74743ad 100644 (file)
@@ -101,6 +101,13 @@ static void __init tegra_dt_init(void)
 
        tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
+       /*
+        * Finished with the static registrations now; fill in the missing
+        * devices
+        */
+       of_platform_populate(NULL, tegra_dt_match_table,
+                               tegra20_auxdata_lookup, NULL);
+
        for (i = 0; i < ARRAY_SIZE(pinmux_configs); i++) {
                if (of_machine_is_compatible(pinmux_configs[i].machine)) {
                        pinmux_configs[i].init();
@@ -110,12 +117,6 @@ static void __init tegra_dt_init(void)
 
        WARN(i == ARRAY_SIZE(pinmux_configs),
                "Unknown platform! Pinmuxing not initialized\n");
-
-       /*
-        * Finished with the static registrations now; fill in the missing
-        * devices
-        */
-       of_platform_populate(NULL, tegra_dt_match_table, tegra20_auxdata_lookup, NULL);
 }
 
 static const char * tegra_dt_board_compat[] = {
index e99b456..7a4a26d 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/kernel.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+
 #include <mach/pinmux.h>
 
 #include "gpio-names.h"
@@ -161,7 +163,9 @@ static struct tegra_gpio_table gpio_table[] = {
 
 void harmony_pinmux_init(void)
 {
-       platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+       if (!of_machine_is_compatible("nvidia,tegra20"))
+               platform_add_devices(pinmux_devices,
+                                       ARRAY_SIZE(pinmux_devices));
 
        tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
 
index fb20894..be30e21 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/kernel.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
+
 #include <mach/pinmux.h>
 
 #include "gpio-names.h"
@@ -158,7 +160,9 @@ static struct tegra_gpio_table gpio_table[] = {
 
 void paz00_pinmux_init(void)
 {
-       platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+       if (!of_machine_is_compatible("nvidia,tegra20"))
+               platform_add_devices(pinmux_devices,
+                                       ARRAY_SIZE(pinmux_devices));
 
        tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
 
index fbce31d..b1c2972 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 
 #include <mach/pinmux.h>
 #include <mach/pinmux-t2.h>
@@ -191,6 +192,7 @@ static struct tegra_gpio_table common_gpio_table[] = {
        { .gpio = TEGRA_GPIO_SD2_POWER,         .enable = true },
        { .gpio = TEGRA_GPIO_LIDSWITCH,         .enable = true },
        { .gpio = TEGRA_GPIO_POWERKEY,          .enable = true },
+       { .gpio = TEGRA_GPIO_HP_DET,            .enable = true },
        { .gpio = TEGRA_GPIO_ISL29018_IRQ,      .enable = true },
        { .gpio = TEGRA_GPIO_CDC_IRQ,           .enable = true },
        { .gpio = TEGRA_GPIO_USB1,              .enable = true },
@@ -218,7 +220,9 @@ static void __init update_pinmux(struct tegra_pingroup_config *newtbl, int size)
 
 void __init seaboard_common_pinmux_init(void)
 {
-       platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+       if (!of_machine_is_compatible("nvidia,tegra20"))
+               platform_add_devices(pinmux_devices,
+                                       ARRAY_SIZE(pinmux_devices));
 
        tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
 
index 4969dd2..7ab719d 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/gpio.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/of.h>
 
 #include <mach/pinmux.h>
 
@@ -157,7 +158,9 @@ static struct tegra_gpio_table gpio_table[] = {
 
 void __init trimslice_pinmux_init(void)
 {
-       platform_add_devices(pinmux_devices, ARRAY_SIZE(pinmux_devices));
+       if (!of_machine_is_compatible("nvidia,tegra20"))
+               platform_add_devices(pinmux_devices,
+                                       ARRAY_SIZE(pinmux_devices));
        tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
        tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
 }
index 7a1fa6a..5b0c38a 100644 (file)
@@ -422,7 +422,7 @@ struct platform_device nuc900_device_kpi = {
 
 /* LCD controller*/
 
-static struct nuc900fb_display __initdata nuc900_lcd_info[] = {
+static struct nuc900fb_display nuc900_lcd_info[] = {
        /* Giantplus Technology GPM1040A0 320x240 Color TFT LCD */
        [0] = {
                .type           = LCM_DCCS_VA_SRC_RGB565,
@@ -445,7 +445,7 @@ static struct nuc900fb_display __initdata nuc900_lcd_info[] = {
        },
 };
 
-static struct nuc900fb_mach_info nuc900_fb_info __initdata = {
+static struct nuc900fb_mach_info nuc900_fb_info = {
 #if defined(CONFIG_GPM1040A0_320X240)
        .displays               = &nuc900_lcd_info[0],
 #else
index 94c0e71..23ef1f5 100644 (file)
@@ -19,6 +19,7 @@
 extern void mfp_set_groupf(struct device *dev);
 extern void mfp_set_groupc(struct device *dev);
 extern void mfp_set_groupi(struct device *dev);
-extern void mfp_set_groupg(struct device *dev);
+extern void mfp_set_groupg(struct device *dev, const char *subname);
+extern void mfp_set_groupd(struct device *dev, const char *subname);
 
 #endif /* __ASM_ARCH_MFP_H */
index bd94819..2c4e0c1 100644 (file)
@@ -14,7 +14,7 @@
 #ifndef __ASM_ARCH_SPI_H
 #define __ASM_ARCH_SPI_H
 
-extern void mfp_set_groupg(struct device *dev);
+extern void mfp_set_groupg(struct device *dev, const char *subname);
 
 struct nuc900_spi_info {
        unsigned int num_cs;
index fb7fb62..9dd7461 100644 (file)
 #define REG_MFSEL      (W90X900_VA_GCR + 0xC)
 
 #define GPSELF         (0x01 << 1)
-
 #define GPSELC         (0x03 << 2)
-#define ENKPI          (0x02 << 2)
-#define ENNAND         (0x01 << 2)
+#define GPSELD         (0x0f << 4)
 
 #define GPSELEI0       (0x01 << 26)
 #define GPSELEI1       (0x01 << 27)
 #define GPIOG0TO1      (0x03 << 14)
 #define GPIOG2TO3      (0x03 << 16)
 #define GPIOG22TO23    (0x03 << 22)
+#define GPIOG18TO20    (0x07 << 18)
 
 #define ENSPI          (0x0a << 14)
 #define ENI2C0         (0x01 << 14)
 #define ENI2C1         (0x01 << 16)
 #define ENAC97         (0x02 << 22)
+#define ENSD1          (0x02 << 18)
+#define ENSD0          (0x0a << 4)
+#define ENKPI          (0x02 << 2)
+#define ENNAND         (0x01 << 2)
 
 static DEFINE_MUTEX(mfp_mutex);
 
@@ -127,16 +130,19 @@ void mfp_set_groupi(struct device *dev)
 }
 EXPORT_SYMBOL(mfp_set_groupi);
 
-void mfp_set_groupg(struct device *dev)
+void mfp_set_groupg(struct device *dev, const char *subname)
 {
        unsigned long mfpen;
        const char *dev_id;
 
-       BUG_ON(!dev);
+       BUG_ON((!dev) && (!subname));
 
        mutex_lock(&mfp_mutex);
 
-       dev_id = dev_name(dev);
+       if (subname != NULL)
+               dev_id = subname;
+       else
+               dev_id = dev_name(dev);
 
        mfpen = __raw_readl(REG_MFSEL);
 
@@ -152,6 +158,9 @@ void mfp_set_groupg(struct device *dev)
        } else if (strcmp(dev_id, "nuc900-audio") == 0) {
                mfpen &= ~(GPIOG22TO23);
                mfpen |= ENAC97;/*enable AC97*/
+       } else if (strcmp(dev_id, "nuc900-mmc-port1") == 0) {
+               mfpen &= ~(GPIOG18TO20);
+               mfpen |= (ENSD1 | 0x01);/*enable sd1*/
        } else {
                mfpen &= ~(GPIOG0TO1 | GPIOG2TO3);/*GPIOG[3:0]*/
        }
@@ -162,3 +171,30 @@ void mfp_set_groupg(struct device *dev)
 }
 EXPORT_SYMBOL(mfp_set_groupg);
 
+void mfp_set_groupd(struct device *dev, const char *subname)
+{
+       unsigned long mfpen;
+       const char *dev_id;
+
+       BUG_ON((!dev) && (!subname));
+
+       mutex_lock(&mfp_mutex);
+
+       if (subname != NULL)
+               dev_id = subname;
+       else
+               dev_id = dev_name(dev);
+
+       mfpen = __raw_readl(REG_MFSEL);
+
+       if (strcmp(dev_id, "nuc900-mmc-port0") == 0) {
+               mfpen &= ~GPSELD;/*enable sd0*/
+               mfpen |= ENSD0;
+       } else
+               mfpen &= (~GPSELD);
+
+       __raw_writel(mfpen, REG_MFSEL);
+
+       mutex_unlock(&mfp_mutex);
+}
+EXPORT_SYMBOL(mfp_set_groupd);
index 8ac9e9f..b1e192b 100644 (file)
@@ -61,7 +61,7 @@ static inline void cache_sync(void)
 {
        void __iomem *base = l2x0_base;
 
-#ifdef CONFIG_ARM_ERRATA_753970
+#ifdef CONFIG_PL310_ERRATA_753970
        /* write to an unmmapped register */
        writel_relaxed(0, base + L2X0_DUMMY_REG);
 #else
index e4e7f6c..1aa664a 100644 (file)
@@ -168,7 +168,7 @@ static int __init consistent_init(void)
        pte_t *pte;
        int i = 0;
        unsigned long base = consistent_base;
-       unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_SHIFT;
+       unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT;
 
        consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
        if (!consistent_pte) {
@@ -332,6 +332,15 @@ __dma_alloc(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp,
        struct page *page;
        void *addr;
 
+       /*
+        * Following is a work-around (a.k.a. hack) to prevent pages
+        * with __GFP_COMP being passed to split_page() which cannot
+        * handle them.  The real problem is that this flag probably
+        * should be 0 on ARM as it is not supported on this
+        * platform; see CONFIG_HUGETLBFS.
+        */
+       gfp &= ~(__GFP_COMP);
+
        *handle = ~0;
        size = PAGE_ALIGN(size);
 
index 74be05f..44b628e 100644 (file)
@@ -9,8 +9,7 @@
 #include <linux/io.h>
 #include <linux/personality.h>
 #include <linux/random.h>
-#include <asm/cputype.h>
-#include <asm/system.h>
+#include <asm/cachetype.h>
 
 #define COLOUR_ALIGN(addr,pgoff)               \
        ((((addr)+SHMLBA-1)&~(SHMLBA-1)) +      \
@@ -32,25 +31,15 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
        struct mm_struct *mm = current->mm;
        struct vm_area_struct *vma;
        unsigned long start_addr;
-#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
-       unsigned int cache_type;
-       int do_align = 0, aliasing = 0;
+       int do_align = 0;
+       int aliasing = cache_is_vipt_aliasing();
 
        /*
         * We only need to do colour alignment if either the I or D
-        * caches alias.  This is indicated by bits 9 and 21 of the
-        * cache type register.
+        * caches alias.
         */
-       cache_type = read_cpuid_cachetype();
-       if (cache_type != read_cpuid_id()) {
-               aliasing = (cache_type | cache_type >> 12) & (1 << 11);
-               if (aliasing)
-                       do_align = filp || flags & MAP_SHARED;
-       }
-#else
-#define do_align 0
-#define aliasing 0
-#endif
+       if (aliasing)
+               do_align = filp || (flags & MAP_SHARED);
 
        /*
         * We enforce the MAP_FIXED case.
index a08a951..b3a1f2b 100644 (file)
@@ -10,7 +10,7 @@ choice
 
 config ARCH_IMX_V4_V5
        bool "i.MX1, i.MX21, i.MX25, i.MX27"
-       select AUTO_ZRELADDR
+       select AUTO_ZRELADDR if !ZBOOT_ROM
        select ARM_PATCH_PHYS_VIRT
        help
          This enables support for systems based on the Freescale i.MX ARMv4
@@ -26,7 +26,7 @@ config ARCH_IMX_V6_V7
 
 config ARCH_MX5
        bool "i.MX50, i.MX51, i.MX53"
-       select AUTO_ZRELADDR
+       select AUTO_ZRELADDR if !ZBOOT_ROM
        select ARM_PATCH_PHYS_VIRT
        help
          This enables support for machines using Freescale's i.MX50 and i.MX53
index 8875fb4..55f1569 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <mach/common.h>
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 #include <mach/hardware.h>
 
 #include "irq-common.h"
index b3b8eed..12f8f81 100644 (file)
@@ -28,21 +28,14 @@ asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
                if (irqnr == 1023)
                        break;
 
-               if (irqnr > 29 && irqnr < 1021)
+               if (irqnr > 15 && irqnr < 1021)
                        handle_IRQ(irqnr, regs);
 #ifdef CONFIG_SMP
-               else if (irqnr < 16) {
+               else {
                        writel_relaxed(irqstat, gic_cpu_base_addr +
                                                GIC_CPU_EOI);
                        handle_IPI(irqnr, regs);
                }
-#endif
-#ifdef CONFIG_LOCAL_TIMERS
-               else if (irqnr == 29) {
-                       writel_relaxed(irqstat, gic_cpu_base_addr +
-                                               GIC_CPU_EOI);
-                       handle_local_timer(regs);
-               }
 #endif
        } while (1);
 }
index 83b745a..c75f254 100644 (file)
@@ -85,7 +85,6 @@ enum mxc_cpu_pwr_mode {
 };
 
 extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
-extern void (*imx_idle)(void);
 extern void imx_print_silicon_rev(const char *cpu, int srev);
 
 void avic_handle_irq(struct pt_regs *);
@@ -133,4 +132,5 @@ extern void imx53_qsb_common_init(void);
 extern void imx53_smd_common_init(void);
 extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
 extern void imx6q_pm_init(void);
+extern void imx6q_clock_map_io(void);
 #endif
index 9fe0dfc..ca5cf26 100644 (file)
@@ -25,6 +25,3 @@
 
        .macro test_for_ipi, irqnr, irqstat, base, tmp
        .endm
-
-       .macro test_for_ltirq, irqnr, irqstat, base, tmp
-       .endm
index 00a7819..a4d36d6 100644 (file)
 #define IMX_CHIP_REVISION_3_3          0x33
 #define IMX_CHIP_REVISION_UNKNOWN      0xff
 
-#define IMX_CHIP_REVISION_1_0_STRING           "1.0"
-#define IMX_CHIP_REVISION_1_1_STRING           "1.1"
-#define IMX_CHIP_REVISION_1_2_STRING           "1.2"
-#define IMX_CHIP_REVISION_1_3_STRING           "1.3"
-#define IMX_CHIP_REVISION_2_0_STRING           "2.0"
-#define IMX_CHIP_REVISION_2_1_STRING           "2.1"
-#define IMX_CHIP_REVISION_2_2_STRING           "2.2"
-#define IMX_CHIP_REVISION_2_3_STRING           "2.3"
-#define IMX_CHIP_REVISION_3_0_STRING           "3.0"
-#define IMX_CHIP_REVISION_3_1_STRING           "3.1"
-#define IMX_CHIP_REVISION_3_2_STRING           "3.2"
-#define IMX_CHIP_REVISION_3_3_STRING           "3.3"
-#define IMX_CHIP_REVISION_UNKNOWN_STRING       "unknown"
-
 #ifndef __ASSEMBLY__
 extern unsigned int __mxc_cpu_type;
 #endif
index cf88b35..b9895d2 100644 (file)
 #ifndef __ASM_ARCH_MXC_SYSTEM_H__
 #define __ASM_ARCH_MXC_SYSTEM_H__
 
-extern void (*imx_idle)(void);
-
 static inline void arch_idle(void)
 {
-       if (imx_idle != NULL)
-               (imx_idle)();
-       else
-               cpu_do_idle();
+       cpu_do_idle();
 }
 
 void arch_reset(char mode, const char *cmd);
index 9dad8dc..d65fb31 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/err.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
@@ -28,8 +29,8 @@
 #include <asm/system.h>
 #include <asm/mach-types.h>
 
-void (*imx_idle)(void) = NULL;
 void __iomem *(*imx_ioremap)(unsigned long, size_t, unsigned int) = NULL;
+EXPORT_SYMBOL_GPL(imx_ioremap);
 
 static void __iomem *wdog_base;
 
index e993a18..a3c164c 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/irq.h>
+#include <asm/exception.h>
 
 #include <mach/hardware.h>
 #include <mach/common.h>
index 197ca03..eb73ab4 100644 (file)
@@ -165,8 +165,8 @@ struct dpll_data {
        u8                      auto_recal_bit;
        u8                      recal_en_bit;
        u8                      recal_st_bit;
-       u8                      flags;
 #  endif
+       u8                      flags;
 };
 
 #endif
index c50df48..3ff3e36 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 
 #include <plat/i2c.h>
+#include <plat/omap_hwmod.h>
 
 struct sys_timer;
 
@@ -55,6 +56,8 @@ void am35xx_init_early(void);
 void ti816x_init_early(void);
 void omap4430_init_early(void);
 
+extern int omap_dss_reset(struct omap_hwmod *);
+
 void omap_sram_init(void);
 
 /*
index a927666..c7adad0 100644 (file)
@@ -12,7 +12,7 @@
 */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/cpufreq.h>
index e1cbc72..c8bec9c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/export.h>
 
 #include <asm/pgtable.h>
 
index d48245b..df8155b 100644 (file)
@@ -24,6 +24,8 @@
 #ifndef __PLAT_GPIO_CFG_H
 #define __PLAT_GPIO_CFG_H __FILE__
 
+#include<linux/types.h>
+
 typedef unsigned int __bitwise__ samsung_gpio_pull_t;
 typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;
 
index efe1d56..312b510 100644 (file)
@@ -11,7 +11,7 @@
 */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
index dc1185d..c559d84 100644 (file)
@@ -11,7 +11,7 @@
  * the Free Software Foundation; either version 2 of the License.
 */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
index 5bdeef9..ccbe16f 100644 (file)
@@ -1123,5 +1123,6 @@ blissc                    MACH_BLISSC             BLISSC                  3491
 thales_adc             MACH_THALES_ADC         THALES_ADC              3492
 ubisys_p9d_evp         MACH_UBISYS_P9D_EVP     UBISYS_P9D_EVP          3493
 atdgp318               MACH_ATDGP318           ATDGP318                3494
+m28evk                 MACH_M28EVK             M28EVK                  3613
 smdk4212               MACH_SMDK4212           SMDK4212                3638
 smdk4412               MACH_SMDK4412           SMDK4412                3765
index 7fd0ec7..ecacdf3 100644 (file)
@@ -32,6 +32,8 @@ struct work_struct;
 struct bfin_serial_port {
        struct uart_port port;
        unsigned int old_status;
+       int tx_irq;
+       int rx_irq;
        int status_irq;
 #ifndef BFIN_UART_BF54X_STYLE
        unsigned int lsr;
index 1082e49..d1c0c0c 100644 (file)
@@ -372,9 +372,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -415,9 +420,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 55c1279..5470bf8 100644 (file)
@@ -308,9 +308,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -351,9 +356,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 8d65d47..5bc6938 100644 (file)
@@ -380,9 +380,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -423,9 +428,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 6410fc1..cd28969 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -538,9 +539,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -581,9 +587,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -801,7 +812,6 @@ static struct platform_device bfin_sport1_uart_device = {
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
-#include <linux/export.h>
 
 static struct gpio_keys_button bfin_gpio_keys_table[] = {
        {BTN_0, GPIO_PF14, 1, "gpio-keys: BTN0"},
index 64f7278..9f792ea 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -416,9 +417,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -459,9 +465,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -674,7 +685,6 @@ static struct platform_device bfin_sport1_uart_device = {
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
-#include <linux/export.h>
 
 static struct gpio_keys_button bfin_gpio_keys_table[] = {
        {BTN_0, GPIO_PG0, 1, "gpio-keys: BTN0"},
index e4c6a12..3ecafff 100644 (file)
@@ -710,9 +710,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -753,9 +758,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 76dbc03..3a92c43 100644 (file)
@@ -495,9 +495,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -539,9 +544,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 5da5787..47cadd3 100644 (file)
@@ -237,9 +237,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index b0ec825..18817d5 100644 (file)
@@ -192,9 +192,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 14f54a3..2c8f30e 100644 (file)
@@ -220,9 +220,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index ecd2801..144556e 100644 (file)
@@ -291,9 +291,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index fbee77f..b597d4e 100644 (file)
@@ -150,9 +150,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 964a8e5..2afd02e 100644 (file)
@@ -297,9 +297,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX + 1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 1471c51..604a430 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/etherdevice.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
@@ -304,9 +305,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -365,9 +371,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -569,7 +580,6 @@ static struct platform_device bfin_sport1_uart_device = {
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
-#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_MII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
index 47cf37d..d916b46 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -305,9 +306,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -348,9 +354,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -534,7 +545,6 @@ static struct platform_device bfin_sport1_uart_device = {
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
-#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_MII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
index 33e69e4..5f30722 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -49,7 +50,6 @@ static struct platform_device rtc_device = {
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
-#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_RMII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
@@ -236,9 +236,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -280,9 +285,14 @@ static struct resource bfin_uart1_resources[] = {
                .end   = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end   = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end   = IRQ_UART1_RX+1,
+               .end   = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index c62f9dc..3901dd0 100644 (file)
@@ -239,9 +239,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -282,9 +287,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 3099e91..aebd31c 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -308,9 +309,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -351,9 +357,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 27f955d..7fbb0bb 100644 (file)
@@ -7,6 +7,7 @@
  */
 
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
@@ -1565,9 +1566,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -1620,9 +1626,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -1992,7 +2003,6 @@ static struct adp8870_backlight_platform_data adp8870_pdata = {
 
 #if defined(CONFIG_BACKLIGHT_ADP8860) || defined(CONFIG_BACKLIGHT_ADP8860_MODULE)
 #include <linux/i2c/adp8860.h>
-#include <linux/export.h>
 static struct led_info adp8860_leds[] = {
        {
                .name = "adp8860-led7",
index 8418030..6917ce2 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/device.h>
 #include <linux/etherdevice.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -305,9 +306,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -348,9 +354,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -536,7 +547,6 @@ static struct platform_device bfin_sport1_uart_device = {
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 #include <linux/bfin_mac.h>
-#include <linux/export.h>
 static const unsigned short bfin_mac_peripherals[] = P_MII0;
 
 static struct bfin_phydev_platform_data bfin_phydev_data[] = {
index 629f3c3..8356eb5 100644 (file)
@@ -48,9 +48,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -103,9 +108,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -146,9 +156,14 @@ static struct resource bfin_uart2_resources[] = {
                .end = UART2_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART2_TX,
+               .end = IRQ_UART2_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART2_RX,
-               .end = IRQ_UART2_RX+1,
+               .end = IRQ_UART2_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 212b9e0..0350eac 100644 (file)
@@ -134,9 +134,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -177,9 +182,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -236,9 +246,14 @@ static struct resource bfin_uart2_resources[] = {
                .end = UART2_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART2_TX,
+               .end = IRQ_UART2_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART2_RX,
-               .end = IRQ_UART2_RX+1,
+               .end = IRQ_UART2_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -279,9 +294,14 @@ static struct resource bfin_uart3_resources[] = {
                .end = UART3_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART3_TX,
+               .end = IRQ_UART3_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART3_RX,
-               .end = IRQ_UART3_RX+1,
+               .end = IRQ_UART3_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index cd9cbb6..bb868ac 100644 (file)
@@ -240,9 +240,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = UART0_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART0_TX,
+               .end = IRQ_UART0_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART0_RX,
-               .end = IRQ_UART0_RX+1,
+               .end = IRQ_UART0_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -283,9 +288,14 @@ static struct resource bfin_uart1_resources[] = {
                .end = UART1_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART1_TX,
+               .end = IRQ_UART1_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART1_RX,
-               .end = IRQ_UART1_RX+1,
+               .end = IRQ_UART1_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -342,9 +352,14 @@ static struct resource bfin_uart2_resources[] = {
                .end = UART2_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART2_TX,
+               .end = IRQ_UART2_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART2_RX,
-               .end = IRQ_UART2_RX+1,
+               .end = IRQ_UART2_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
@@ -385,9 +400,14 @@ static struct resource bfin_uart3_resources[] = {
                .end = UART3_RBR+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART3_TX,
+               .end = IRQ_UART3_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART3_RX,
-               .end = IRQ_UART3_RX+1,
+               .end = IRQ_UART3_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 972e134..b1b7339 100644 (file)
@@ -202,9 +202,14 @@ static struct resource bfin_uart0_resources[] = {
         .end = BFIN_UART_GCTL + 2,
         .flags = IORESOURCE_MEM,
         },
+       {
+        .start = IRQ_UART_TX,
+        .end = IRQ_UART_TX,
+        .flags = IORESOURCE_IRQ,
+        },
        {
         .start = IRQ_UART_RX,
-        .end = IRQ_UART_RX + 1,
+        .end = IRQ_UART_RX,
         .flags = IORESOURCE_IRQ,
         },
        {
index c1b72f2..c017cf0 100644 (file)
@@ -276,9 +276,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART_TX,
+               .end = IRQ_UART_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART_RX,
-               .end = IRQ_UART_RX+1,
+               .end = IRQ_UART_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 9490dc8..27f22ed 100644 (file)
@@ -171,9 +171,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART_TX,
+               .end = IRQ_UART_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART_RX,
-               .end = IRQ_UART_RX+1,
+               .end = IRQ_UART_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index bb056e6..1a57bc9 100644 (file)
@@ -50,9 +50,14 @@ static struct resource bfin_uart0_resources[] = {
                .end = BFIN_UART_GCTL+2,
                .flags = IORESOURCE_MEM,
        },
+       {
+               .start = IRQ_UART_TX,
+               .end = IRQ_UART_TX,
+               .flags = IORESOURCE_IRQ,
+       },
        {
                .start = IRQ_UART_RX,
-               .end = IRQ_UART_RX+1,
+               .end = IRQ_UART_RX,
                .flags = IORESOURCE_IRQ,
        },
        {
index 32d9086..5f2cdb3 100644 (file)
@@ -3,7 +3,7 @@ if ETRAX_ARCH_V10
 config ETRAX_ETHERNET
        bool "Ethernet support"
        depends on ETRAX_ARCH_V10
-       select NET_ETHERNET
+       select ETHERNET
        select NET_CORE
        select MII
        help
index e47e9c3..de43aad 100644 (file)
@@ -3,7 +3,7 @@ if ETRAX_ARCH_V32
 config ETRAX_ETHERNET
        bool "Ethernet support"
        depends on ETRAX_ARCH_V32
-       select NET_ETHERNET
+       select ETHERNET
        select NET_CORE
        select MII
        help
index 6c28582..361d540 100644 (file)
@@ -4,8 +4,8 @@ config M68K
        select HAVE_IDE
        select HAVE_AOUT if MMU
        select GENERIC_ATOMIC64 if MMU
-       select HAVE_GENERIC_HARDIRQS if !MMU
-       select GENERIC_IRQ_SHOW if !MMU
+       select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_SHOW
        select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
 
 config RWSEM_GENERIC_SPINLOCK
index 8294f0c..3adb499 100644 (file)
@@ -2,6 +2,15 @@ if MMU
 
 comment "Bus Support"
 
+config DIO
+       bool "DIO bus support"
+       depends on HP300
+       default y
+       help
+         Say Y here to enable support for the "DIO" expansion bus used in
+         HP300 machines. If you are using such a system you almost certainly
+         want this.
+
 config NUBUS
        bool
        depends on MAC
index d214034..6033f5d 100644 (file)
@@ -24,6 +24,37 @@ config PROC_HARDWARE
          including the model, CPU, MMU, clock speed, BogoMIPS rating,
          and memory size.
 
+config NATFEAT
+       bool "ARAnyM emulator support"
+       depends on ATARI
+       help
+         This option enables support for ARAnyM native features, such as
+         access to a disk image as /dev/hda.
+
+config NFBLOCK
+       tristate "NatFeat block device support"
+       depends on BLOCK && NATFEAT
+       help
+         Say Y to include support for the ARAnyM NatFeat block device
+         which allows direct access to the hard drives without using
+         the hardware emulation.
+
+config NFCON
+       tristate "NatFeat console driver"
+       depends on NATFEAT
+       help
+         Say Y to include support for the ARAnyM NatFeat console driver
+         which allows the console output to be redirected to the stderr
+         output of ARAnyM.
+
+config NFETH
+       tristate "NatFeat Ethernet support"
+       depends on ETHERNET && NATFEAT
+       help
+         Say Y to include support for the ARAnyM NatFeat network device
+         which will emulate a regular ethernet device while presenting an
+         ethertap device to the host system.
+
 endmenu
 
 menu "Character devices"
index c5b5212..47b5f90 100644 (file)
@@ -1,43 +1,15 @@
 /*
- * linux/arch/m68k/amiga/amiints.c -- Amiga Linux interrupt handling code
+ * Amiga Linux interrupt handling code
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
- *
- * 11/07/96: rewritten interrupt handling, irq lists are exists now only for
- *           this sources where it makes sense (VERTB/PORTS/EXTER) and you must
- *           be careful that dev_id for this sources is unique since this the
- *           only possibility to distinguish between different handlers for
- *           free_irq. irq lists also have different irq flags:
- *           - IRQ_FLG_FAST: handler is inserted at top of list (after other
- *                           fast handlers)
- *           - IRQ_FLG_SLOW: handler is inserted at bottom of list and before
- *                           they're executed irq level is set to the previous
- *                           one, but handlers don't need to be reentrant, if
- *                           reentrance occurred, slow handlers will be just
- *                           called again.
- *           The whole interrupt handling for CIAs is moved to cia.c
- *           /Roman Zippel
- *
- * 07/08/99: rewamp of the interrupt handling - we now have two types of
- *           interrupts, normal and fast handlers, fast handlers being
- *           marked with IRQF_DISABLED and runs with all other interrupts
- *           disabled. Normal interrupts disable their own source but
- *           run with all other interrupt sources enabled.
- *           PORTS and EXTER interrupts are always shared even if the
- *           drivers do not explicitly mark this when calling
- *           request_irq which they really should do.
- *           This is similar to the way interrupts are handled on all
- *           other architectures and makes a ton of sense besides
- *           having the advantage of making it easier to share
- *           drivers.
- *           /Jes
  */
 
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
+#include <linux/irq.h>
 
 #include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/amigaints.h>
 #include <asm/amipcmcia.h>
 
-static void amiga_enable_irq(unsigned int irq);
-static void amiga_disable_irq(unsigned int irq);
-static irqreturn_t ami_int1(int irq, void *dev_id);
-static irqreturn_t ami_int3(int irq, void *dev_id);
-static irqreturn_t ami_int4(int irq, void *dev_id);
-static irqreturn_t ami_int5(int irq, void *dev_id);
-
-static struct irq_controller amiga_irq_controller = {
-       .name           = "amiga",
-       .lock           = __SPIN_LOCK_UNLOCKED(amiga_irq_controller.lock),
-       .enable         = amiga_enable_irq,
-       .disable        = amiga_disable_irq,
-};
-
-/*
- * void amiga_init_IRQ(void)
- *
- * Parameters: None
- *
- * Returns:    Nothing
- *
- * This function should be called during kernel startup to initialize
- * the amiga IRQ handling routines.
- */
-
-void __init amiga_init_IRQ(void)
-{
-       if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
-               pr_err("Couldn't register int%d\n", 1);
-       if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
-               pr_err("Couldn't register int%d\n", 3);
-       if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
-               pr_err("Couldn't register int%d\n", 4);
-       if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
-               pr_err("Couldn't register int%d\n", 5);
-
-       m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
-
-       /* turn off PCMCIA interrupts */
-       if (AMIGAHW_PRESENT(PCMCIA))
-               gayle.inten = GAYLE_IRQ_IDE;
-
-       /* turn off all interrupts and enable the master interrupt bit */
-       amiga_custom.intena = 0x7fff;
-       amiga_custom.intreq = 0x7fff;
-       amiga_custom.intena = IF_SETCLR | IF_INTEN;
-
-       cia_init_IRQ(&ciaa_base);
-       cia_init_IRQ(&ciab_base);
-}
 
 /*
  * Enable/disable a particular machine specific interrupt source.
@@ -103,112 +25,150 @@ void __init amiga_init_IRQ(void)
  * internal data, that may not be changed by the interrupt at the same time.
  */
 
-static void amiga_enable_irq(unsigned int irq)
+static void amiga_irq_enable(struct irq_data *data)
 {
-       amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER));
+       amiga_custom.intena = IF_SETCLR | (1 << (data->irq - IRQ_USER));
 }
 
-static void amiga_disable_irq(unsigned int irq)
+static void amiga_irq_disable(struct irq_data *data)
 {
-       amiga_custom.intena = 1 << (irq - IRQ_USER);
+       amiga_custom.intena = 1 << (data->irq - IRQ_USER);
 }
 
+static struct irq_chip amiga_irq_chip = {
+       .name           = "amiga",
+       .irq_enable     = amiga_irq_enable,
+       .irq_disable    = amiga_irq_disable,
+};
+
+
 /*
  * The builtin Amiga hardware interrupt handlers.
  */
 
-static irqreturn_t ami_int1(int irq, void *dev_id)
+static void ami_int1(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
        /* if serial transmit buffer empty, interrupt */
        if (ints & IF_TBE) {
                amiga_custom.intreq = IF_TBE;
-               m68k_handle_int(IRQ_AMIGA_TBE);
+               generic_handle_irq(IRQ_AMIGA_TBE);
        }
 
        /* if floppy disk transfer complete, interrupt */
        if (ints & IF_DSKBLK) {
                amiga_custom.intreq = IF_DSKBLK;
-               m68k_handle_int(IRQ_AMIGA_DSKBLK);
+               generic_handle_irq(IRQ_AMIGA_DSKBLK);
        }
 
        /* if software interrupt set, interrupt */
        if (ints & IF_SOFT) {
                amiga_custom.intreq = IF_SOFT;
-               m68k_handle_int(IRQ_AMIGA_SOFT);
+               generic_handle_irq(IRQ_AMIGA_SOFT);
        }
-       return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int3(int irq, void *dev_id)
+static void ami_int3(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
        /* if a blitter interrupt */
        if (ints & IF_BLIT) {
                amiga_custom.intreq = IF_BLIT;
-               m68k_handle_int(IRQ_AMIGA_BLIT);
+               generic_handle_irq(IRQ_AMIGA_BLIT);
        }
 
        /* if a copper interrupt */
        if (ints & IF_COPER) {
                amiga_custom.intreq = IF_COPER;
-               m68k_handle_int(IRQ_AMIGA_COPPER);
+               generic_handle_irq(IRQ_AMIGA_COPPER);
        }
 
        /* if a vertical blank interrupt */
        if (ints & IF_VERTB) {
                amiga_custom.intreq = IF_VERTB;
-               m68k_handle_int(IRQ_AMIGA_VERTB);
+               generic_handle_irq(IRQ_AMIGA_VERTB);
        }
-       return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int4(int irq, void *dev_id)
+static void ami_int4(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
        /* if audio 0 interrupt */
        if (ints & IF_AUD0) {
                amiga_custom.intreq = IF_AUD0;
-               m68k_handle_int(IRQ_AMIGA_AUD0);
+               generic_handle_irq(IRQ_AMIGA_AUD0);
        }
 
        /* if audio 1 interrupt */
        if (ints & IF_AUD1) {
                amiga_custom.intreq = IF_AUD1;
-               m68k_handle_int(IRQ_AMIGA_AUD1);
+               generic_handle_irq(IRQ_AMIGA_AUD1);
        }
 
        /* if audio 2 interrupt */
        if (ints & IF_AUD2) {
                amiga_custom.intreq = IF_AUD2;
-               m68k_handle_int(IRQ_AMIGA_AUD2);
+               generic_handle_irq(IRQ_AMIGA_AUD2);
        }
 
        /* if audio 3 interrupt */
        if (ints & IF_AUD3) {
                amiga_custom.intreq = IF_AUD3;
-               m68k_handle_int(IRQ_AMIGA_AUD3);
+               generic_handle_irq(IRQ_AMIGA_AUD3);
        }
-       return IRQ_HANDLED;
 }
 
-static irqreturn_t ami_int5(int irq, void *dev_id)
+static void ami_int5(unsigned int irq, struct irq_desc *desc)
 {
        unsigned short ints = amiga_custom.intreqr & amiga_custom.intenar;
 
        /* if serial receive buffer full interrupt */
        if (ints & IF_RBF) {
                /* acknowledge of IF_RBF must be done by the serial interrupt */
-               m68k_handle_int(IRQ_AMIGA_RBF);
+               generic_handle_irq(IRQ_AMIGA_RBF);
        }
 
        /* if a disk sync interrupt */
        if (ints & IF_DSKSYN) {
                amiga_custom.intreq = IF_DSKSYN;
-               m68k_handle_int(IRQ_AMIGA_DSKSYN);
+               generic_handle_irq(IRQ_AMIGA_DSKSYN);
        }
-       return IRQ_HANDLED;
+}
+
+
+/*
+ * void amiga_init_IRQ(void)
+ *
+ * Parameters: None
+ *
+ * Returns:    Nothing
+ *
+ * This function should be called during kernel startup to initialize
+ * the amiga IRQ handling routines.
+ */
+
+void __init amiga_init_IRQ(void)
+{
+       m68k_setup_irq_controller(&amiga_irq_chip, handle_simple_irq, IRQ_USER,
+                                 AMI_STD_IRQS);
+
+       irq_set_chained_handler(IRQ_AUTO_1, ami_int1);
+       irq_set_chained_handler(IRQ_AUTO_3, ami_int3);
+       irq_set_chained_handler(IRQ_AUTO_4, ami_int4);
+       irq_set_chained_handler(IRQ_AUTO_5, ami_int5);
+
+       /* turn off PCMCIA interrupts */
+       if (AMIGAHW_PRESENT(PCMCIA))
+               gayle.inten = GAYLE_IRQ_IDE;
+
+       /* turn off all interrupts and enable the master interrupt bit */
+       amiga_custom.intena = 0x7fff;
+       amiga_custom.intreq = 0x7fff;
+       amiga_custom.intena = IF_SETCLR | IF_INTEN;
+
+       cia_init_IRQ(&ciaa_base);
+       cia_init_IRQ(&ciab_base);
 }
index ecd0f7c..18c0e29 100644 (file)
@@ -93,13 +93,14 @@ static irqreturn_t cia_handler(int irq, void *dev_id)
        amiga_custom.intreq = base->int_mask;
        for (; ints; mach_irq++, ints >>= 1) {
                if (ints & 1)
-                       m68k_handle_int(mach_irq);
+                       generic_handle_irq(mach_irq);
        }
        return IRQ_HANDLED;
 }
 
-static void cia_enable_irq(unsigned int irq)
+static void cia_irq_enable(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
        unsigned char mask;
 
        if (irq >= IRQ_AMIGA_CIAB) {
@@ -113,19 +114,20 @@ static void cia_enable_irq(unsigned int irq)
        }
 }
 
-static void cia_disable_irq(unsigned int irq)
+static void cia_irq_disable(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        if (irq >= IRQ_AMIGA_CIAB)
                cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB));
        else
                cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA));
 }
 
-static struct irq_controller cia_irq_controller = {
+static struct irq_chip cia_irq_chip = {
        .name           = "cia",
-       .lock           = __SPIN_LOCK_UNLOCKED(cia_irq_controller.lock),
-       .enable         = cia_enable_irq,
-       .disable        = cia_disable_irq,
+       .irq_enable     = cia_irq_enable,
+       .irq_disable    = cia_irq_disable,
 };
 
 /*
@@ -134,9 +136,9 @@ static struct irq_controller cia_irq_controller = {
  * into this chain.
  */
 
-static void auto_enable_irq(unsigned int irq)
+static void auto_irq_enable(struct irq_data *data)
 {
-       switch (irq) {
+       switch (data->irq) {
        case IRQ_AUTO_2:
                amiga_custom.intena = IF_SETCLR | IF_PORTS;
                break;
@@ -146,9 +148,9 @@ static void auto_enable_irq(unsigned int irq)
        }
 }
 
-static void auto_disable_irq(unsigned int irq)
+static void auto_irq_disable(struct irq_data *data)
 {
-       switch (irq) {
+       switch (data->irq) {
        case IRQ_AUTO_2:
                amiga_custom.intena = IF_PORTS;
                break;
@@ -158,24 +160,25 @@ static void auto_disable_irq(unsigned int irq)
        }
 }
 
-static struct irq_controller auto_irq_controller = {
+static struct irq_chip auto_irq_chip = {
        .name           = "auto",
-       .lock           = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
-       .enable         = auto_enable_irq,
-       .disable        = auto_disable_irq,
+       .irq_enable     = auto_irq_enable,
+       .irq_disable    = auto_irq_disable,
 };
 
 void __init cia_init_IRQ(struct ciabase *base)
 {
-       m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS);
+       m68k_setup_irq_controller(&cia_irq_chip, handle_simple_irq,
+                                 base->cia_irq, CIA_IRQS);
 
        /* clear any pending interrupt and turn off all interrupts */
        cia_set_irq(base, CIA_ICR_ALL);
        cia_able_irq(base, CIA_ICR_ALL);
 
        /* override auto int and install CIA handler */
-       m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
-       m68k_irq_startup(base->handler_irq);
+       m68k_setup_irq_controller(&auto_irq_chip, handle_simple_irq,
+                                 base->handler_irq, 1);
+       m68k_irq_startup_irq(base->handler_irq);
        if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
                        base->name, base))
                pr_err("Couldn't register %s interrupt\n", base->name);
index 5d47f3a..17be1e7 100644 (file)
@@ -1,19 +1,13 @@
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
-#include <asm/irq.h>
 #include <asm/traps.h>
 #include <asm/apollohw.h>
 
-void dn_process_int(unsigned int irq, struct pt_regs *fp)
+unsigned int apollo_irq_startup(struct irq_data *data)
 {
-       __m68k_handle_int(irq, fp);
+       unsigned int irq = data->irq;
 
-       *(volatile unsigned char *)(pica)=0x20;
-       *(volatile unsigned char *)(picb)=0x20;
-}
-
-int apollo_irq_startup(unsigned int irq)
-{
        if (irq < 8)
                *(volatile unsigned char *)(pica+1) &= ~(1 << irq);
        else
@@ -21,24 +15,33 @@ int apollo_irq_startup(unsigned int irq)
        return 0;
 }
 
-void apollo_irq_shutdown(unsigned int irq)
+void apollo_irq_shutdown(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        if (irq < 8)
                *(volatile unsigned char *)(pica+1) |= (1 << irq);
        else
                *(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
 }
 
-static struct irq_controller apollo_irq_controller = {
+void apollo_irq_eoi(struct irq_data *data)
+{
+       *(volatile unsigned char *)(pica) = 0x20;
+       *(volatile unsigned char *)(picb) = 0x20;
+}
+
+static struct irq_chip apollo_irq_chip = {
        .name           = "apollo",
-       .lock           = __SPIN_LOCK_UNLOCKED(apollo_irq_controller.lock),
-       .startup        = apollo_irq_startup,
-       .shutdown       = apollo_irq_shutdown,
+       .irq_startup    = apollo_irq_startup,
+       .irq_shutdown   = apollo_irq_shutdown,
+       .irq_eoi        = apollo_irq_eoi,
 };
 
 
 void __init dn_init_IRQ(void)
 {
-       m68k_setup_user_interrupt(VEC_USER + 96, 16, dn_process_int);
-       m68k_setup_irq_controller(&apollo_irq_controller, IRQ_APOLLO, 16);
+       m68k_setup_user_interrupt(VEC_USER + 96, 16);
+       m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq,
+                                 IRQ_APOLLO, 16);
 }
index 26a804e..6d196da 100644 (file)
  * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
  * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
  * be allocated by atari_register_vme_int().
- *
- * Each interrupt can be of three types:
- *
- *  - SLOW: The handler runs with all interrupts enabled, except the one it
- *    was called by (to avoid reentering). This should be the usual method.
- *    But it is currently possible only for MFP ints, since only the MFP
- *    offers an easy way to mask interrupts.
- *
- *  - FAST: The handler runs with all interrupts disabled. This should be used
- *    only for really fast handlers, that just do actions immediately
- *    necessary, and let the rest do a bottom half or task queue.
- *
- *  - PRIORITIZED: The handler can be interrupted by higher-level ints
- *    (greater IPL, no MFP priorities!). This is the method of choice for ints
- *    which should be slow, but are not from a MFP.
- *
- * The feature of more than one handler for one int source is still there, but
- * only applicable if all handers are of the same type. To not slow down
- * processing of ints with only one handler by the chaining feature, the list
- * calling function atari_call_irq_list() is only plugged in at the time the
- * second handler is registered.
- *
- * Implementation notes: For fast-as-possible int handling, there are separate
- * entry points for each type (slow/fast/prio). The assembler handler calls
- * the irq directly in the usual case, no C wrapper is involved. In case of
- * multiple handlers, atari_call_irq_list() is registered as handler and calls
- * in turn the real irq's. To ease access from assembler level to the irq
- * function pointer and accompanying data, these two are stored in a separate
- * array, irq_handler[]. The rest of data (type, name) are put into a second
- * array, irq_param, that is accessed from C only. For each slow interrupt (32
- * in all) there are separate handler functions, which makes it possible to
- * hard-code the MFP register address and value, are necessary to mask the
- * int. If there'd be only one generic function, lots of calculations would be
- * needed to determine MFP register and int mask from the vector number :-(
- *
- * Furthermore, slow ints may not lower the IPL below its previous value
- * (before the int happened). This is needed so that an int of class PRIO, on
- * that this int may be stacked, cannot be reentered. This feature is
- * implemented as follows: If the stack frame format is 1 (throwaway), the int
- * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
- * 2, which still blocks the HSYNC, but no interrupts of interest. If the
- * frame format is 0, the int is nested, and the old IPL value can be found in
- * the sr copy in the frame.
- */
-
-#if 0
-
-#define        NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES)
-
-typedef void (*asm_irq_handler)(void);
-
-struct irqhandler {
-       irqreturn_t (*handler)(int, void *, struct pt_regs *);
-       void    *dev_id;
-};
-
-struct irqparam {
-       unsigned long   flags;
-       const char      *devname;
-};
-
-/*
- * Array with irq's and their parameter data. This array is accessed from low
- * level assembler code, so an element size of 8 allows usage of index scaling
- * addressing mode.
  */
-static struct irqhandler irq_handler[NUM_INT_SOURCES];
-
-/*
- * This array hold the rest of parameters of int handlers: type
- * (slow,fast,prio) and the name of the handler. These values are only
- * accessed from C
- */
-static struct irqparam irq_param[NUM_INT_SOURCES];
-
-/* check for valid int number (complex, sigh...) */
-#define        IS_VALID_INTNO(n)                                                                                       \
-       ((n) > 0 &&                                                                                                             \
-        /* autovec and ST-MFP ok anyway */                                                             \
-        (((n) < TTMFP_SOURCE_BASE) ||                                                                  \
-         /* TT-MFP ok if present */                                                                    \
-         ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE &&                 \
-          ATARIHW_PRESENT(TT_MFP)) ||                                                                  \
-         /* SCC ok if present and number even */                                               \
-         ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE &&                   \
-          !((n) & 1) && ATARIHW_PRESENT(SCC)) ||                                               \
-         /* greater numbers ok if they are registered VME vectors */           \
-         ((n) >= VME_SOURCE_BASE && (n) < VME_SOURCE_BASE + VME_MAX_SOURCES && \
-                 free_vme_vec_bitmap & (1 << ((n) - VME_SOURCE_BASE)))))
-
-
-/*
- * Here start the assembler entry points for interrupts
- */
-
-#define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
-
-#define        BUILD_SLOW_IRQ(n)                                                  \
-asmlinkage void IRQ_NAME(n);                                              \
-/* Dummy function to allow asm with operands.  */                         \
-void atari_slow_irq_##n##_dummy (void) {                                  \
-__asm__ (__ALIGN_STR "\n"                                                 \
-"atari_slow_irq_" #n "_handler:\t"                                        \
-"      addl    %6,%5\n"        /* preempt_count() += HARDIRQ_OFFSET */    \
-       SAVE_ALL_INT "\n"                                                  \
-       GET_CURRENT(%%d0) "\n"                                             \
-"      andb    #~(1<<(%c3&7)),%a4:w\n" /* mask this interrupt */          \
-       /* get old IPL from stack frame */                                 \
-"      bfextu  %%sp@(%c2){#5,#3},%%d0\n"                                  \
-"      movew   %%sr,%%d1\n"                                               \
-"      bfins   %%d0,%%d1{#21,#3}\n"                                       \
-"      movew   %%d1,%%sr\n"            /* set IPL = previous value */     \
-"      addql   #1,%a0\n"                                                  \
-"      lea     %a1,%%a0\n"                                                \
-"      pea     %%sp@\n"                /* push addr of frame */           \
-"      movel   %%a0@(4),%%sp@-\n"      /* push handler data */            \
-"      pea     (%c3+8)\n"              /* push int number */              \
-"      movel   %%a0@,%%a0\n"                                              \
-"      jbsr    %%a0@\n"                /* call the handler */             \
-"      addql   #8,%%sp\n"                                                 \
-"      addql   #4,%%sp\n"                                                 \
-"      orw     #0x0600,%%sr\n"                                            \
-"      andw    #0xfeff,%%sr\n"         /* set IPL = 6 again */            \
-"      orb     #(1<<(%c3&7)),%a4:w\n"  /* now unmask the int again */     \
-"      jbra    ret_from_interrupt\n"                                      \
-        : : "i" (&kstat_cpu(0).irqs[n+8]), "i" (&irq_handler[n+8]),       \
-            "n" (PT_OFF_SR), "n" (n),                                     \
-            "i" (n & 8 ? (n & 16 ? &tt_mfp.int_mk_a : &st_mfp.int_mk_a)   \
-                       : (n & 16 ? &tt_mfp.int_mk_b : &st_mfp.int_mk_b)), \
-            "m" (preempt_count()), "di" (HARDIRQ_OFFSET)                  \
-);                                                                        \
-       for (;;);                       /* fake noreturn */                \
-}
-
-BUILD_SLOW_IRQ(0);
-BUILD_SLOW_IRQ(1);
-BUILD_SLOW_IRQ(2);
-BUILD_SLOW_IRQ(3);
-BUILD_SLOW_IRQ(4);
-BUILD_SLOW_IRQ(5);
-BUILD_SLOW_IRQ(6);
-BUILD_SLOW_IRQ(7);
-BUILD_SLOW_IRQ(8);
-BUILD_SLOW_IRQ(9);
-BUILD_SLOW_IRQ(10);
-BUILD_SLOW_IRQ(11);
-BUILD_SLOW_IRQ(12);
-BUILD_SLOW_IRQ(13);
-BUILD_SLOW_IRQ(14);
-BUILD_SLOW_IRQ(15);
-BUILD_SLOW_IRQ(16);
-BUILD_SLOW_IRQ(17);
-BUILD_SLOW_IRQ(18);
-BUILD_SLOW_IRQ(19);
-BUILD_SLOW_IRQ(20);
-BUILD_SLOW_IRQ(21);
-BUILD_SLOW_IRQ(22);
-BUILD_SLOW_IRQ(23);
-BUILD_SLOW_IRQ(24);
-BUILD_SLOW_IRQ(25);
-BUILD_SLOW_IRQ(26);
-BUILD_SLOW_IRQ(27);
-BUILD_SLOW_IRQ(28);
-BUILD_SLOW_IRQ(29);
-BUILD_SLOW_IRQ(30);
-BUILD_SLOW_IRQ(31);
-
-asm_irq_handler slow_handlers[32] = {
-       [0]     = atari_slow_irq_0_handler,
-       [1]     = atari_slow_irq_1_handler,
-       [2]     = atari_slow_irq_2_handler,
-       [3]     = atari_slow_irq_3_handler,
-       [4]     = atari_slow_irq_4_handler,
-       [5]     = atari_slow_irq_5_handler,
-       [6]     = atari_slow_irq_6_handler,
-       [7]     = atari_slow_irq_7_handler,
-       [8]     = atari_slow_irq_8_handler,
-       [9]     = atari_slow_irq_9_handler,
-       [10]    = atari_slow_irq_10_handler,
-       [11]    = atari_slow_irq_11_handler,
-       [12]    = atari_slow_irq_12_handler,
-       [13]    = atari_slow_irq_13_handler,
-       [14]    = atari_slow_irq_14_handler,
-       [15]    = atari_slow_irq_15_handler,
-       [16]    = atari_slow_irq_16_handler,
-       [17]    = atari_slow_irq_17_handler,
-       [18]    = atari_slow_irq_18_handler,
-       [19]    = atari_slow_irq_19_handler,
-       [20]    = atari_slow_irq_20_handler,
-       [21]    = atari_slow_irq_21_handler,
-       [22]    = atari_slow_irq_22_handler,
-       [23]    = atari_slow_irq_23_handler,
-       [24]    = atari_slow_irq_24_handler,
-       [25]    = atari_slow_irq_25_handler,
-       [26]    = atari_slow_irq_26_handler,
-       [27]    = atari_slow_irq_27_handler,
-       [28]    = atari_slow_irq_28_handler,
-       [29]    = atari_slow_irq_29_handler,
-       [30]    = atari_slow_irq_30_handler,
-       [31]    = atari_slow_irq_31_handler
-};
-
-asmlinkage void atari_fast_irq_handler( void );
-asmlinkage void atari_prio_irq_handler( void );
-
-/* Dummy function to allow asm with operands.  */
-void atari_fast_prio_irq_dummy (void) {
-__asm__ (__ALIGN_STR "\n"
-"atari_fast_irq_handler:\n\t"
-       "orw    #0x700,%%sr\n"          /* disable all interrupts */
-"atari_prio_irq_handler:\n\t"
-       "addl   %3,%2\n\t"              /* preempt_count() += HARDIRQ_OFFSET */
-       SAVE_ALL_INT "\n\t"
-       GET_CURRENT(%%d0) "\n\t"
-       /* get vector number from stack frame and convert to source */
-       "bfextu %%sp@(%c1){#4,#10},%%d0\n\t"
-       "subw   #(0x40-8),%%d0\n\t"
-       "jpl    1f\n\t"
-       "addw   #(0x40-8-0x18),%%d0\n"
-    "1:\tlea   %a0,%%a0\n\t"
-       "addql  #1,%%a0@(%%d0:l:4)\n\t"
-       "lea    irq_handler,%%a0\n\t"
-       "lea    %%a0@(%%d0:l:8),%%a0\n\t"
-       "pea    %%sp@\n\t"              /* push frame address */
-       "movel  %%a0@(4),%%sp@-\n\t"    /* push handler data */
-       "movel  %%d0,%%sp@-\n\t"        /* push int number */
-       "movel  %%a0@,%%a0\n\t"
-       "jsr    %%a0@\n\t"              /* and call the handler */
-       "addql  #8,%%sp\n\t"
-       "addql  #4,%%sp\n\t"
-       "jbra   ret_from_interrupt"
-        : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC),
-            "m" (preempt_count()), "di" (HARDIRQ_OFFSET)
-);
-       for (;;);
-}
-#endif
 
 /*
  * Bitmap for free interrupt vector numbers
@@ -320,31 +84,44 @@ extern void atari_microwire_cmd(int cmd);
 
 extern int atari_SCC_reset_done;
 
-static int atari_startup_irq(unsigned int irq)
+static unsigned int atari_irq_startup(struct irq_data *data)
 {
-       m68k_irq_startup(irq);
+       unsigned int irq = data->irq;
+
+       m68k_irq_startup(data);
        atari_turnon_irq(irq);
        atari_enable_irq(irq);
        return 0;
 }
 
-static void atari_shutdown_irq(unsigned int irq)
+static void atari_irq_shutdown(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        atari_disable_irq(irq);
        atari_turnoff_irq(irq);
-       m68k_irq_shutdown(irq);
+       m68k_irq_shutdown(data);
 
        if (irq == IRQ_AUTO_4)
            vectors[VEC_INT4] = falcon_hblhandler;
 }
 
-static struct irq_controller atari_irq_controller = {
+static void atari_irq_enable(struct irq_data *data)
+{
+       atari_enable_irq(data->irq);
+}
+
+static void atari_irq_disable(struct irq_data *data)
+{
+       atari_disable_irq(data->irq);
+}
+
+static struct irq_chip atari_irq_chip = {
        .name           = "atari",
-       .lock           = __SPIN_LOCK_UNLOCKED(atari_irq_controller.lock),
-       .startup        = atari_startup_irq,
-       .shutdown       = atari_shutdown_irq,
-       .enable         = atari_enable_irq,
-       .disable        = atari_disable_irq,
+       .irq_startup    = atari_irq_startup,
+       .irq_shutdown   = atari_irq_shutdown,
+       .irq_enable     = atari_irq_enable,
+       .irq_disable    = atari_irq_disable,
 };
 
 /*
@@ -360,8 +137,9 @@ static struct irq_controller atari_irq_controller = {
 
 void __init atari_init_IRQ(void)
 {
-       m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER, NULL);
-       m68k_setup_irq_controller(&atari_irq_controller, 1, NUM_ATARI_SOURCES - 1);
+       m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER);
+       m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1,
+                                 NUM_ATARI_SOURCES - 1);
 
        /* Initialize the MFP(s) */
 
index 1edd950..8128647 100644 (file)
@@ -86,7 +86,7 @@ static void bvme6000_get_model(char *model)
  */
 static void __init bvme6000_init_IRQ(void)
 {
-       m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+       m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 void __init config_bvme6000(void)
index f6312c7..c87fe69 100644 (file)
@@ -70,7 +70,7 @@ void __init hp300_sched_init(irq_handler_t vector)
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
+  if (request_irq(IRQ_AUTO_6, hp300_tick, 0, "timer tick", vector))
     pr_err("Couldn't register timer interrupt\n");
 
   out_8(CLOCKBASE + CLKCR2, 0x1);              /* select CR1 */
index 870e534..db30ed2 100644 (file)
 
 #ifdef CONFIG_MMU
 
+static inline void ack_bad_irq(unsigned int irq)
+{
+       pr_crit("unexpected IRQ trap at vector %02x\n", irq);
+}
+
 /* entry.S is sensitive to the offsets of these fields */
 typedef struct {
        unsigned int __softirq_pending;
index 69ed0d7..6198df5 100644 (file)
 
 #ifdef CONFIG_MMU
 
-#include <linux/linkage.h>
-#include <linux/hardirq.h>
-#include <linux/irqreturn.h>
-#include <linux/spinlock_types.h>
-
 /*
  * Interrupt source definitions
  * General interrupt sources are the level 1-7.
 
 #define IRQ_USER       8
 
-extern unsigned int irq_canonicalize(unsigned int irq);
-
-struct pt_regs;
-
 /*
  * various flags for request_irq() - the Amiga now uses the standard
  * mechanism like all other architectures - IRQF_DISABLED and
@@ -71,57 +62,27 @@ struct pt_regs;
 #define IRQ_FLG_STD    (0x8000)        /* internally used              */
 #endif
 
-/*
- * This structure is used to chain together the ISRs for a particular
- * interrupt source (if it supports chaining).
- */
-typedef struct irq_node {
-       irqreturn_t     (*handler)(int, void *);
-       void            *dev_id;
-       struct irq_node *next;
-       unsigned long   flags;
-       const char      *devname;
-} irq_node_t;
-
-/*
- * This structure has only 4 elements for speed reasons
- */
-struct irq_handler {
-       int             (*handler)(int, void *);
-       unsigned long   flags;
-       void            *dev_id;
-       const char      *devname;
-};
-
-struct irq_controller {
-       const char *name;
-       spinlock_t lock;
-       int (*startup)(unsigned int irq);
-       void (*shutdown)(unsigned int irq);
-       void (*enable)(unsigned int irq);
-       void (*disable)(unsigned int irq);
-};
-
-extern int m68k_irq_startup(unsigned int);
-extern void m68k_irq_shutdown(unsigned int);
-
-/*
- * This function returns a new irq_node_t
- */
-extern irq_node_t *new_irq_node(void);
+struct irq_data;
+struct irq_chip;
+struct irq_desc;
+extern unsigned int m68k_irq_startup(struct irq_data *data);
+extern unsigned int m68k_irq_startup_irq(unsigned int irq);
+extern void m68k_irq_shutdown(struct irq_data *data);
+extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int,
+                                                     struct pt_regs *));
+extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt);
+extern void m68k_setup_irq_controller(struct irq_chip *,
+                                     void (*handle)(unsigned int irq,
+                                                    struct irq_desc *desc),
+                                     unsigned int irq, unsigned int cnt);
 
-extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-                                     void (*handler)(unsigned int, struct pt_regs *));
-extern void m68k_setup_irq_controller(struct irq_controller *, unsigned int, unsigned int);
-
-asmlinkage void m68k_handle_int(unsigned int);
-asmlinkage void __m68k_handle_int(unsigned int, struct pt_regs *);
+extern unsigned int irq_canonicalize(unsigned int irq);
 
 #else
 #define irq_canonicalize(irq)  (irq)
 #endif /* CONFIG_MMU */
 
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
+extern atomic_t irq_err_count;
 
 #endif /* _M68K_IRQ_H_ */
index c2a1c5e..12ebe43 100644 (file)
@@ -12,6 +12,8 @@ extern void mac_reset(void);
 extern void mac_poweroff(void);
 extern void mac_init_IRQ(void);
 extern int mac_irq_pending(unsigned int);
+extern void mac_irq_enable(struct irq_data *data);
+extern void mac_irq_disable(struct irq_data *data);
 
 /*
  *     Floppy driver magic hook - probably shouldn't be here
index 3d970af..22f12c9 100644 (file)
@@ -24,6 +24,3 @@
 #define Q40_IRQ10_MASK       (1<<5)
 #define Q40_IRQ14_MASK       (1<<6)
 #define Q40_IRQ15_MASK       (1<<7)
-
-extern unsigned long q40_probe_irq_on (void);
-extern int q40_probe_irq_off (unsigned long irqs);
index e7f0f2e..c569619 100644 (file)
@@ -6,16 +6,15 @@ extra-$(CONFIG_MMU)   := head.o
 extra-$(CONFIG_SUN3)   := sun3-head.o
 extra-y                        += vmlinux.lds
 
-obj-y  := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \
-          sys_m68k.o syscalltable.o time.o traps.o
+obj-y  := entry.o irq.o m68k_ksyms.o module.o process.o ptrace.o setup.o \
+          signal.o sys_m68k.o syscalltable.o time.o traps.o
 
-obj-$(CONFIG_MMU)      += ints.o devres.o vectors.o
-devres-$(CONFIG_MMU)   = ../../../kernel/irq/devres.o
+obj-$(CONFIG_MMU)      += ints.o vectors.o
 
 ifndef CONFIG_MMU_SUN3
 obj-y                  += dma.o
 endif
 ifndef CONFIG_MMU
-obj-y                  += init_task.o irq.o
+obj-y                  += init_task.o
 endif
 
index bd0ec05..c713f51 100644 (file)
@@ -48,7 +48,7 @@
 .globl sys_fork, sys_clone, sys_vfork
 .globl ret_from_interrupt, bad_interrupt
 .globl auto_irqhandler_fixup
-.globl user_irqvec_fixup, user_irqhandler_fixup
+.globl user_irqvec_fixup
 
 .text
 ENTRY(buserr)
@@ -207,7 +207,7 @@ ENTRY(auto_inthandler)
        movel   %sp,%sp@-
        movel   %d0,%sp@-               |  put vector # on stack
 auto_irqhandler_fixup = . + 2
-       jsr     __m68k_handle_int       |  process the IRQ
+       jsr     do_IRQ                  |  process the IRQ
        addql   #8,%sp                  |  pop parameters off stack
 
 ret_from_interrupt:
@@ -240,8 +240,7 @@ user_irqvec_fixup = . + 2
 
        movel   %sp,%sp@-
        movel   %d0,%sp@-               |  put vector # on stack
-user_irqhandler_fixup = . + 2
-       jsr     __m68k_handle_int       |  process the IRQ
+       jsr     do_IRQ                  |  process the IRQ
        addql   #8,%sp                  |  pop parameters off stack
 
        subqb   #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
index 761ee04..74fefac 100644 (file)
@@ -4,25 +4,6 @@
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
  * for more details.
- *
- * 07/03/96: Timer initialization, and thus mach_sched_init(),
- *           removed from request_irq() and moved to init_time().
- *           We should therefore consider renaming our add_isr() and
- *           remove_isr() to request_irq() and free_irq()
- *           respectively, so they are compliant with the other
- *           architectures.                                     /Jes
- * 11/07/96: Changed all add_/remove_isr() to request_/free_irq() calls.
- *           Removed irq list support, if any machine needs an irq server
- *           it must implement this itself (as it's already done), instead
- *           only default handler are used with mach_default_handler.
- *           request_irq got some flags different from other architectures:
- *           - IRQ_FLG_REPLACE : Replace an existing handler (the default one
- *                               can be replaced without this flag)
- *           - IRQ_FLG_LOCK : handler can't be replaced
- *           There are other machine depending flags, see there
- *           If you want to replace a default handler you should know what
- *           you're doing, since it might handle different other irq sources
- *           which must be served                               /Roman Zippel
  */
 
 #include <linux/module.h>
 #endif
 
 extern u32 auto_irqhandler_fixup[];
-extern u32 user_irqhandler_fixup[];
 extern u16 user_irqvec_fixup[];
 
-/* table for system interrupt handlers */
-static struct irq_node *irq_list[NR_IRQS];
-static struct irq_controller *irq_controller[NR_IRQS];
-static int irq_depth[NR_IRQS];
-
 static int m68k_first_user_vec;
 
-static struct irq_controller auto_irq_controller = {
+static struct irq_chip auto_irq_chip = {
        .name           = "auto",
-       .lock           = __SPIN_LOCK_UNLOCKED(auto_irq_controller.lock),
-       .startup        = m68k_irq_startup,
-       .shutdown       = m68k_irq_shutdown,
+       .irq_startup    = m68k_irq_startup,
+       .irq_shutdown   = m68k_irq_shutdown,
 };
 
-static struct irq_controller user_irq_controller = {
+static struct irq_chip user_irq_chip = {
        .name           = "user",
-       .lock           = __SPIN_LOCK_UNLOCKED(user_irq_controller.lock),
-       .startup        = m68k_irq_startup,
-       .shutdown       = m68k_irq_shutdown,
+       .irq_startup    = m68k_irq_startup,
+       .irq_shutdown   = m68k_irq_shutdown,
 };
 
-#define NUM_IRQ_NODES 100
-static irq_node_t nodes[NUM_IRQ_NODES];
-
 /*
  * void init_IRQ(void)
  *
@@ -96,7 +66,7 @@ void __init init_IRQ(void)
        }
 
        for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
-               irq_controller[i] = &auto_irq_controller;
+               irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);
 
        mach_init_IRQ();
 }
@@ -106,7 +76,7 @@ void __init init_IRQ(void)
  * @handler: called from auto vector interrupts
  *
  * setup the handler to be called from auto vector interrupts instead of the
- * standard __m68k_handle_int(), it will be called with irq numbers in the range
+ * standard do_IRQ(), it will be called with irq numbers in the range
  * from IRQ_AUTO_1 - IRQ_AUTO_7.
  */
 void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_regs *))
@@ -120,217 +90,49 @@ void __init m68k_setup_auto_interrupt(void (*handler)(unsigned int, struct pt_re
  * m68k_setup_user_interrupt
  * @vec: first user vector interrupt to handle
  * @cnt: number of active user vector interrupts
- * @handler: called from user vector interrupts
  *
  * setup user vector interrupts, this includes activating the specified range
  * of interrupts, only then these interrupts can be requested (note: this is
- * different from auto vector interrupts). An optional handler can be installed
- * to be called instead of the default __m68k_handle_int(), it will be called
- * with irq numbers starting from IRQ_USER.
+ * different from auto vector interrupts).
  */
-void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
-                                     void (*handler)(unsigned int, struct pt_regs *))
+void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt)
 {
        int i;
 
        BUG_ON(IRQ_USER + cnt > NR_IRQS);
        m68k_first_user_vec = vec;
        for (i = 0; i < cnt; i++)
-               irq_controller[IRQ_USER + i] = &user_irq_controller;
+               irq_set_chip(IRQ_USER + i, &user_irq_chip);
        *user_irqvec_fixup = vec - IRQ_USER;
-       if (handler)
-               *user_irqhandler_fixup = (u32)handler;
        flush_icache();
 }
 
 /**
  * m68k_setup_irq_controller
- * @contr: irq controller which controls specified irq
+ * @chip: irq chip which controls specified irq
+ * @handle: flow handler which handles specified irq
  * @irq: first irq to be managed by the controller
+ * @cnt: number of irqs to be managed by the controller
  *
  * Change the controller for the specified range of irq, which will be used to
  * manage these irq. auto/user irq already have a default controller, which can
  * be changed as well, but the controller probably should use m68k_irq_startup/
  * m68k_irq_shutdown.
  */
-void m68k_setup_irq_controller(struct irq_controller *contr, unsigned int irq,
+void m68k_setup_irq_controller(struct irq_chip *chip,
+                              irq_flow_handler_t handle, unsigned int irq,
                               unsigned int cnt)
 {
        int i;
 
-       for (i = 0; i < cnt; i++)
-               irq_controller[irq + i] = contr;
-}
-
-irq_node_t *new_irq_node(void)
-{
-       irq_node_t *node;
-       short i;
-
-       for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--) {
-               if (!node->handler) {
-                       memset(node, 0, sizeof(*node));
-                       return node;
-               }
+       for (i = 0; i < cnt; i++) {
+               irq_set_chip(irq + i, chip);
+               if (handle)
+                       irq_set_handler(irq + i, handle);
        }
-
-       printk ("new_irq_node: out of nodes\n");
-       return NULL;
 }
 
-int setup_irq(unsigned int irq, struct irq_node *node)
-{
-       struct irq_controller *contr;
-       struct irq_node **prev;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-               printk("%s: Incorrect IRQ %d from %s\n",
-                      __func__, irq, node->devname);
-               return -ENXIO;
-       }
-
-       spin_lock_irqsave(&contr->lock, flags);
-
-       prev = irq_list + irq;
-       if (*prev) {
-               /* Can't share interrupts unless both agree to */
-               if (!((*prev)->flags & node->flags & IRQF_SHARED)) {
-                       spin_unlock_irqrestore(&contr->lock, flags);
-                       return -EBUSY;
-               }
-               while (*prev)
-                       prev = &(*prev)->next;
-       }
-
-       if (!irq_list[irq]) {
-               if (contr->startup)
-                       contr->startup(irq);
-               else
-                       contr->enable(irq);
-       }
-       node->next = NULL;
-       *prev = node;
-
-       spin_unlock_irqrestore(&contr->lock, flags);
-
-       return 0;
-}
-
-int request_irq(unsigned int irq,
-               irq_handler_t handler,
-               unsigned long flags, const char *devname, void *dev_id)
-{
-       struct irq_node *node;
-       int res;
-
-       node = new_irq_node();
-       if (!node)
-               return -ENOMEM;
-
-       node->handler = handler;
-       node->flags   = flags;
-       node->dev_id  = dev_id;
-       node->devname = devname;
-
-       res = setup_irq(irq, node);
-       if (res)
-               node->handler = NULL;
-
-       return res;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-       struct irq_controller *contr;
-       struct irq_node **p, *node;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-               printk("%s: Incorrect IRQ %d\n", __func__, irq);
-               return;
-       }
-
-       spin_lock_irqsave(&contr->lock, flags);
-
-       p = irq_list + irq;
-       while ((node = *p)) {
-               if (node->dev_id == dev_id)
-                       break;
-               p = &node->next;
-       }
-
-       if (node) {
-               *p = node->next;
-               node->handler = NULL;
-       } else
-               printk("%s: Removing probably wrong IRQ %d\n",
-                      __func__, irq);
-
-       if (!irq_list[irq]) {
-               if (contr->shutdown)
-                       contr->shutdown(irq);
-               else
-                       contr->disable(irq);
-       }
-
-       spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(free_irq);
-
-void enable_irq(unsigned int irq)
-{
-       struct irq_controller *contr;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-               printk("%s: Incorrect IRQ %d\n",
-                      __func__, irq);
-               return;
-       }
-
-       spin_lock_irqsave(&contr->lock, flags);
-       if (irq_depth[irq]) {
-               if (!--irq_depth[irq]) {
-                       if (contr->enable)
-                               contr->enable(irq);
-               }
-       } else
-               WARN_ON(1);
-       spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(enable_irq);
-
-void disable_irq(unsigned int irq)
-{
-       struct irq_controller *contr;
-       unsigned long flags;
-
-       if (irq >= NR_IRQS || !(contr = irq_controller[irq])) {
-               printk("%s: Incorrect IRQ %d\n",
-                      __func__, irq);
-               return;
-       }
-
-       spin_lock_irqsave(&contr->lock, flags);
-       if (!irq_depth[irq]++) {
-               if (contr->disable)
-                       contr->disable(irq);
-       }
-       spin_unlock_irqrestore(&contr->lock, flags);
-}
-
-EXPORT_SYMBOL(disable_irq);
-
-void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
-
-EXPORT_SYMBOL(disable_irq_nosync);
-
-int m68k_irq_startup(unsigned int irq)
+unsigned int m68k_irq_startup_irq(unsigned int irq)
 {
        if (irq <= IRQ_AUTO_7)
                vectors[VEC_SPUR + irq] = auto_inthandler;
@@ -339,41 +141,21 @@ int m68k_irq_startup(unsigned int irq)
        return 0;
 }
 
-void m68k_irq_shutdown(unsigned int irq)
+unsigned int m68k_irq_startup(struct irq_data *data)
 {
-       if (irq <= IRQ_AUTO_7)
-               vectors[VEC_SPUR + irq] = bad_inthandler;
-       else
-               vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
+       return m68k_irq_startup_irq(data->irq);
 }
 
-
-/*
- * Do we need these probe functions on the m68k?
- *
- *  ... may be useful with ISA devices
- */
-unsigned long probe_irq_on (void)
+void m68k_irq_shutdown(struct irq_data *data)
 {
-#ifdef CONFIG_Q40
-       if (MACH_IS_Q40)
-               return q40_probe_irq_on();
-#endif
-       return 0;
-}
+       unsigned int irq = data->irq;
 
-EXPORT_SYMBOL(probe_irq_on);
-
-int probe_irq_off (unsigned long irqs)
-{
-#ifdef CONFIG_Q40
-       if (MACH_IS_Q40)
-               return q40_probe_irq_off(irqs);
-#endif
-       return 0;
+       if (irq <= IRQ_AUTO_7)
+               vectors[VEC_SPUR + irq] = bad_inthandler;
+       else
+               vectors[m68k_first_user_vec + irq - IRQ_USER] = bad_inthandler;
 }
 
-EXPORT_SYMBOL(probe_irq_off);
 
 unsigned int irq_canonicalize(unsigned int irq)
 {
@@ -386,52 +168,9 @@ unsigned int irq_canonicalize(unsigned int irq)
 
 EXPORT_SYMBOL(irq_canonicalize);
 
-asmlinkage void m68k_handle_int(unsigned int irq)
-{
-       struct irq_node *node;
-       kstat_cpu(0).irqs[irq]++;
-       node = irq_list[irq];
-       do {
-               node->handler(irq, node->dev_id);
-               node = node->next;
-       } while (node);
-}
-
-asmlinkage void __m68k_handle_int(unsigned int irq, struct pt_regs *regs)
-{
-       struct pt_regs *old_regs;
-       old_regs = set_irq_regs(regs);
-       m68k_handle_int(irq);
-       set_irq_regs(old_regs);
-}
 
 asmlinkage void handle_badint(struct pt_regs *regs)
 {
-       kstat_cpu(0).irqs[0]++;
-       printk("unexpected interrupt from %u\n", regs->vector);
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-       struct irq_controller *contr;
-       struct irq_node *node;
-       int i = *(loff_t *) v;
-
-       /* autovector interrupts */
-       if (irq_list[i]) {
-               contr = irq_controller[i];
-               node = irq_list[i];
-               seq_printf(p, "%-8s %3u: %10u %s", contr->name, i, kstat_cpu(0).irqs[i], node->devname);
-               while ((node = node->next))
-                       seq_printf(p, ", %s", node->devname);
-               seq_puts(p, "\n");
-       }
-       return 0;
-}
-
-#ifdef CONFIG_PROC_FS
-void init_irq_proc(void)
-{
-       /* Insert /proc/irq driver here */
+       atomic_inc(&irq_err_count);
+       pr_warn("unexpected interrupt from %u\n", regs->vector);
 }
-#endif
index 2a96beb..b403924 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/traps.h>
 #include <asm/bootinfo.h>
@@ -20,9 +21,6 @@
 
 /* #define DEBUG_IRQS */
 
-extern void mac_enable_irq(unsigned int);
-extern void mac_disable_irq(unsigned int);
-
 int baboon_present;
 static volatile struct baboon *baboon;
 static unsigned char baboon_disabled;
@@ -53,7 +51,7 @@ void __init baboon_init(void)
  * Baboon interrupt handler. This works a lot like a VIA.
  */
 
-static irqreturn_t baboon_irq(int irq, void *dev_id)
+static void baboon_irq(unsigned int irq, struct irq_desc *desc)
 {
        int irq_bit, irq_num;
        unsigned char events;
@@ -64,15 +62,16 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
                (uint) baboon->mb_status);
 #endif
 
-       if (!(events = baboon->mb_ifr & 0x07))
-               return IRQ_NONE;
+       events = baboon->mb_ifr & 0x07;
+       if (!events)
+               return;
 
        irq_num = IRQ_BABOON_0;
        irq_bit = 1;
        do {
                if (events & irq_bit) {
                        baboon->mb_ifr &= ~irq_bit;
-                       m68k_handle_int(irq_num);
+                       generic_handle_irq(irq_num);
                }
                irq_bit <<= 1;
                irq_num++;
@@ -82,7 +81,6 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
        /* for now we need to smash all interrupts */
        baboon->mb_ifr &= ~events;
 #endif
-       return IRQ_HANDLED;
 }
 
 /*
@@ -92,8 +90,7 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
 void __init baboon_register_interrupts(void)
 {
        baboon_disabled = 0;
-       if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
-               pr_err("Couldn't register baboon interrupt\n");
+       irq_set_chained_handler(IRQ_NUBUS_C, baboon_irq);
 }
 
 /*
@@ -111,7 +108,7 @@ void baboon_irq_enable(int irq)
 
        baboon_disabled &= ~(1 << irq_idx);
        if (!baboon_disabled)
-               mac_enable_irq(IRQ_NUBUS_C);
+               mac_irq_enable(irq_get_irq_data(IRQ_NUBUS_C));
 }
 
 void baboon_irq_disable(int irq)
@@ -124,7 +121,7 @@ void baboon_irq_disable(int irq)
 
        baboon_disabled |= 1 << irq_idx;
        if (baboon_disabled)
-               mac_disable_irq(IRQ_NUBUS_C);
+               mac_irq_disable(irq_get_irq_data(IRQ_NUBUS_C));
 }
 
 void baboon_irq_clear(int irq)
index 1ad4e9d..a5462cc 100644 (file)
@@ -305,15 +305,13 @@ void __init iop_register_interrupts(void)
 {
        if (iop_ism_present) {
                if (oss_present) {
-                       if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
-                                       IRQ_FLG_LOCK, "ISM IOP",
-                                       (void *) IOP_NUM_ISM))
+                       if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq, 0,
+                                       "ISM IOP", (void *)IOP_NUM_ISM))
                                pr_err("Couldn't register ISM IOP interrupt\n");
                        oss_irq_enable(IRQ_MAC_ADB);
                } else {
-                       if (request_irq(IRQ_VIA2_0, iop_ism_irq,
-                                       IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
-                                       (void *) IOP_NUM_ISM))
+                       if (request_irq(IRQ_VIA2_0, iop_ism_irq, 0, "ISM IOP",
+                                       (void *)IOP_NUM_ISM))
                                pr_err("Couldn't register ISM IOP interrupt\n");
                }
                if (!iop_alive(iop_base[IOP_NUM_ISM])) {
index f92190c..ba220b7 100644 (file)
@@ -190,14 +190,10 @@ irqreturn_t mac_debug_handler(int, void *);
 
 /* #define DEBUG_MACINTS */
 
-void mac_enable_irq(unsigned int irq);
-void mac_disable_irq(unsigned int irq);
-
-static struct irq_controller mac_irq_controller = {
+static struct irq_chip mac_irq_chip = {
        .name           = "mac",
-       .lock           = __SPIN_LOCK_UNLOCKED(mac_irq_controller.lock),
-       .enable         = mac_enable_irq,
-       .disable        = mac_disable_irq,
+       .irq_enable     = mac_irq_enable,
+       .irq_disable    = mac_irq_disable,
 };
 
 void __init mac_init_IRQ(void)
@@ -205,7 +201,7 @@ void __init mac_init_IRQ(void)
 #ifdef DEBUG_MACINTS
        printk("mac_init_IRQ(): Setting things up...\n");
 #endif
-       m68k_setup_irq_controller(&mac_irq_controller, IRQ_USER,
+       m68k_setup_irq_controller(&mac_irq_chip, handle_simple_irq, IRQ_USER,
                                  NUM_MAC_SOURCES - IRQ_USER);
        /* Make sure the SONIC interrupt is cleared or things get ugly */
 #ifdef SHUTUP_SONIC
@@ -241,16 +237,17 @@ void __init mac_init_IRQ(void)
 }
 
 /*
- *  mac_enable_irq - enable an interrupt source
- * mac_disable_irq - disable an interrupt source
+ *  mac_irq_enable - enable an interrupt source
+ * mac_irq_disable - disable an interrupt source
  *   mac_clear_irq - clears a pending interrupt
- * mac_pending_irq - Returns the pending status of an IRQ (nonzero = pending)
+ * mac_irq_pending - returns the pending status of an IRQ (nonzero = pending)
  *
  * These routines are just dispatchers to the VIA/OSS/PSC routines.
  */
 
-void mac_enable_irq(unsigned int irq)
+void mac_irq_enable(struct irq_data *data)
 {
+       int irq = data->irq;
        int irq_src = IRQ_SRC(irq);
 
        switch(irq_src) {
@@ -283,8 +280,9 @@ void mac_enable_irq(unsigned int irq)
        }
 }
 
-void mac_disable_irq(unsigned int irq)
+void mac_irq_disable(struct irq_data *data)
 {
+       int irq = data->irq;
        int irq_src = IRQ_SRC(irq);
 
        switch(irq_src) {
index a9c0f5a..a4c82da 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
 int oss_present;
 volatile struct mac_oss *oss;
 
-static irqreturn_t oss_irq(int, void *);
-static irqreturn_t oss_nubus_irq(int, void *);
-
-extern irqreturn_t via1_irq(int, void *);
+extern void via1_irq(unsigned int irq, struct irq_desc *desc);
 
 /*
  * Initialize the OSS
@@ -59,26 +57,6 @@ void __init oss_init(void)
        oss->irq_level[OSS_VIA1] = OSS_IRQLEV_VIA1;
 }
 
-/*
- * Register the OSS and NuBus interrupt dispatchers.
- */
-
-void __init oss_register_interrupts(void)
-{
-       if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
-                       "scsi", (void *) oss))
-               pr_err("Couldn't register %s interrupt\n", "scsi");
-       if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
-                       "nubus", (void *) oss))
-               pr_err("Couldn't register %s interrupt\n", "nubus");
-       if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
-                       "sound", (void *) oss))
-               pr_err("Couldn't register %s interrupt\n", "sound");
-       if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
-                       "via1", (void *) via1))
-               pr_err("Couldn't register %s interrupt\n", "via1");
-}
-
 /*
  * Initialize OSS for Nubus access
  */
@@ -92,17 +70,17 @@ void __init oss_nubus_init(void)
  * and SCSI; everything else is routed to its own autovector IRQ.
  */
 
-static irqreturn_t oss_irq(int irq, void *dev_id)
+static void oss_irq(unsigned int irq, struct irq_desc *desc)
 {
        int events;
 
        events = oss->irq_pending & (OSS_IP_SOUND|OSS_IP_SCSI);
        if (!events)
-               return IRQ_NONE;
+               return;
 
 #ifdef DEBUG_IRQS
        if ((console_loglevel == 10) && !(events & OSS_IP_SCSI)) {
-               printk("oss_irq: irq %d events = 0x%04X\n", irq,
+               printk("oss_irq: irq %u events = 0x%04X\n", irq,
                        (int) oss->irq_pending);
        }
 #endif
@@ -113,11 +91,10 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
                /* FIXME: call sound handler */
        } else if (events & OSS_IP_SCSI) {
                oss->irq_pending &= ~OSS_IP_SCSI;
-               m68k_handle_int(IRQ_MAC_SCSI);
+               generic_handle_irq(IRQ_MAC_SCSI);
        } else {
                /* FIXME: error check here? */
        }
-       return IRQ_HANDLED;
 }
 
 /*
@@ -126,13 +103,13 @@ static irqreturn_t oss_irq(int irq, void *dev_id)
  * Unlike the VIA/RBV this is on its own autovector interrupt level.
  */
 
-static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
+static void oss_nubus_irq(unsigned int irq, struct irq_desc *desc)
 {
        int events, irq_bit, i;
 
        events = oss->irq_pending & OSS_IP_NUBUS;
        if (!events)
-               return IRQ_NONE;
+               return;
 
 #ifdef DEBUG_NUBUS_INT
        if (console_loglevel > 7) {
@@ -148,10 +125,21 @@ static irqreturn_t oss_nubus_irq(int irq, void *dev_id)
                irq_bit >>= 1;
                if (events & irq_bit) {
                        oss->irq_pending &= ~irq_bit;
-                       m68k_handle_int(NUBUS_SOURCE_BASE + i);
+                       generic_handle_irq(NUBUS_SOURCE_BASE + i);
                }
        } while(events & (irq_bit - 1));
-       return IRQ_HANDLED;
+}
+
+/*
+ * Register the OSS and NuBus interrupt dispatchers.
+ */
+
+void __init oss_register_interrupts(void)
+{
+       irq_set_chained_handler(OSS_IRQLEV_SCSI, oss_irq);
+       irq_set_chained_handler(OSS_IRQLEV_NUBUS, oss_nubus_irq);
+       irq_set_chained_handler(OSS_IRQLEV_SOUND, oss_irq);
+       irq_set_chained_handler(OSS_IRQLEV_VIA1, via1_irq);
 }
 
 /*
index a4c3eb6..e6c2d20 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/mm.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/irq.h>
 
 #include <asm/traps.h>
 #include <asm/bootinfo.h>
@@ -30,8 +31,6 @@
 int psc_present;
 volatile __u8 *psc;
 
-irqreturn_t psc_irq(int, void *);
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
@@ -111,53 +110,53 @@ void __init psc_init(void)
        }
 }
 
-/*
- * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
- */
-
-void __init psc_register_interrupts(void)
-{
-       if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
-               pr_err("Couldn't register psc%d interrupt\n", 3);
-       if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
-               pr_err("Couldn't register psc%d interrupt\n", 4);
-       if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
-               pr_err("Couldn't register psc%d interrupt\n", 5);
-       if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
-               pr_err("Couldn't register psc%d interrupt\n", 6);
-}
-
 /*
  * PSC interrupt handler. It's a lot like the VIA interrupt handler.
  */
 
-irqreturn_t psc_irq(int irq, void *dev_id)
+static void psc_irq(unsigned int irq, struct irq_desc *desc)
 {
-       int pIFR        = pIFRbase + ((int) dev_id);
-       int pIER        = pIERbase + ((int) dev_id);
+       unsigned int offset = (unsigned int)irq_desc_get_handler_data(desc);
+       int pIFR        = pIFRbase + offset;
+       int pIER        = pIERbase + offset;
        int irq_num;
        unsigned char irq_bit, events;
 
 #ifdef DEBUG_IRQS
-       printk("psc_irq: irq %d pIFR = 0x%02X pIER = 0x%02X\n",
+       printk("psc_irq: irq %u pIFR = 0x%02X pIER = 0x%02X\n",
                irq, (int) psc_read_byte(pIFR), (int) psc_read_byte(pIER));
 #endif
 
        events = psc_read_byte(pIFR) & psc_read_byte(pIER) & 0xF;
        if (!events)
-               return IRQ_NONE;
+               return;
 
        irq_num = irq << 3;
        irq_bit = 1;
        do {
                if (events & irq_bit) {
                        psc_write_byte(pIFR, irq_bit);
-                       m68k_handle_int(irq_num);
+                       generic_handle_irq(irq_num);
                }
                irq_num++;
                irq_bit <<= 1;
        } while (events >= irq_bit);
-       return IRQ_HANDLED;
+}
+
+/*
+ * Register the PSC interrupt dispatchers for autovector interrupts 3-6.
+ */
+
+void __init psc_register_interrupts(void)
+{
+       irq_set_chained_handler(IRQ_AUTO_3, psc_irq);
+       irq_set_handler_data(IRQ_AUTO_3, (void *)0x30);
+       irq_set_chained_handler(IRQ_AUTO_4, psc_irq);
+       irq_set_handler_data(IRQ_AUTO_4, (void *)0x40);
+       irq_set_chained_handler(IRQ_AUTO_5, psc_irq);
+       irq_set_handler_data(IRQ_AUTO_5, (void *)0x50);
+       irq_set_chained_handler(IRQ_AUTO_6, psc_irq);
+       irq_set_handler_data(IRQ_AUTO_6, (void *)0x60);
 }
 
 void psc_irq_enable(int irq) {
index e71166d..f1600ad 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 
 #include <asm/bootinfo.h>
 #include <asm/macintosh.h>
@@ -77,9 +78,6 @@ static int gIER,gIFR,gBufA,gBufB;
 static u8 nubus_disabled;
 
 void via_debug_dump(void);
-irqreturn_t via1_irq(int, void *);
-irqreturn_t via2_irq(int, void *);
-irqreturn_t via_nubus_irq(int, void *);
 void via_irq_enable(int irq);
 void via_irq_disable(int irq);
 void via_irq_clear(int irq);
@@ -281,39 +279,10 @@ void __init via_init_clock(irq_handler_t func)
        via1[vT1CL] = MAC_CLOCK_LOW;
        via1[vT1CH] = MAC_CLOCK_HIGH;
 
-       if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
+       if (request_irq(IRQ_MAC_TIMER_1, func, 0, "timer", func))
                pr_err("Couldn't register %s interrupt\n", "timer");
 }
 
-/*
- * Register the interrupt dispatchers for VIA or RBV machines only.
- */
-
-void __init via_register_interrupts(void)
-{
-       if (via_alt_mapping) {
-               if (request_irq(IRQ_AUTO_1, via1_irq,
-                               IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
-                               (void *) via1))
-                       pr_err("Couldn't register %s interrupt\n", "software");
-               if (request_irq(IRQ_AUTO_6, via1_irq,
-                               IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-                               (void *) via1))
-                       pr_err("Couldn't register %s interrupt\n", "via1");
-       } else {
-               if (request_irq(IRQ_AUTO_1, via1_irq,
-                               IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-                               (void *) via1))
-                       pr_err("Couldn't register %s interrupt\n", "via1");
-       }
-       if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-                       "via2", (void *) via2))
-               pr_err("Couldn't register %s interrupt\n", "via2");
-       if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
-                       IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
-               pr_err("Couldn't register %s interrupt\n", "nubus");
-}
-
 /*
  * Debugging dump, used in various places to see what's going on.
  */
@@ -446,48 +415,46 @@ void __init via_nubus_init(void)
  * via6522.c :-), disable/pending masks added.
  */
 
-irqreturn_t via1_irq(int irq, void *dev_id)
+void via1_irq(unsigned int irq, struct irq_desc *desc)
 {
        int irq_num;
        unsigned char irq_bit, events;
 
        events = via1[vIFR] & via1[vIER] & 0x7F;
        if (!events)
-               return IRQ_NONE;
+               return;
 
        irq_num = VIA1_SOURCE_BASE;
        irq_bit = 1;
        do {
                if (events & irq_bit) {
                        via1[vIFR] = irq_bit;
-                       m68k_handle_int(irq_num);
+                       generic_handle_irq(irq_num);
                }
                ++irq_num;
                irq_bit <<= 1;
        } while (events >= irq_bit);
-       return IRQ_HANDLED;
 }
 
-irqreturn_t via2_irq(int irq, void *dev_id)
+static void via2_irq(unsigned int irq, struct irq_desc *desc)
 {
        int irq_num;
        unsigned char irq_bit, events;
 
        events = via2[gIFR] & via2[gIER] & 0x7F;
        if (!events)
-               return IRQ_NONE;
+               return;
 
        irq_num = VIA2_SOURCE_BASE;
        irq_bit = 1;
        do {
                if (events & irq_bit) {
                        via2[gIFR] = irq_bit | rbv_clear;
-                       m68k_handle_int(irq_num);
+                       generic_handle_irq(irq_num);
                }
                ++irq_num;
                irq_bit <<= 1;
        } while (events >= irq_bit);
-       return IRQ_HANDLED;
 }
 
 /*
@@ -495,7 +462,7 @@ irqreturn_t via2_irq(int irq, void *dev_id)
  * VIA2 dispatcher as a fast interrupt handler.
  */
 
-irqreturn_t via_nubus_irq(int irq, void *dev_id)
+void via_nubus_irq(unsigned int irq, struct irq_desc *desc)
 {
        int slot_irq;
        unsigned char slot_bit, events;
@@ -506,7 +473,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
        else
                events &= ~via2[vDirA];
        if (!events)
-               return IRQ_NONE;
+               return;
 
        do {
                slot_irq = IRQ_NUBUS_F;
@@ -514,7 +481,7 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
                do {
                        if (events & slot_bit) {
                                events &= ~slot_bit;
-                               m68k_handle_int(slot_irq);
+                               generic_handle_irq(slot_irq);
                        }
                        --slot_irq;
                        slot_bit >>= 1;
@@ -528,7 +495,24 @@ irqreturn_t via_nubus_irq(int irq, void *dev_id)
                else
                        events &= ~via2[vDirA];
        } while (events);
-       return IRQ_HANDLED;
+}
+
+/*
+ * Register the interrupt dispatchers for VIA or RBV machines only.
+ */
+
+void __init via_register_interrupts(void)
+{
+       if (via_alt_mapping) {
+               /* software interrupt */
+               irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
+               /* via1 interrupt */
+               irq_set_chained_handler(IRQ_AUTO_6, via1_irq);
+       } else {
+               irq_set_chained_handler(IRQ_AUTO_1, via1_irq);
+       }
+       irq_set_chained_handler(IRQ_AUTO_2, via2_irq);
+       irq_set_chained_handler(IRQ_MAC_NUBUS, via_nubus_irq);
 }
 
 void via_irq_enable(int irq) {
index 6cb9c3a..5de924e 100644 (file)
@@ -81,7 +81,7 @@ static void mvme147_get_model(char *model)
 
 void __init mvme147_init_IRQ(void)
 {
-       m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+       m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 void __init config_mvme147(void)
@@ -114,8 +114,7 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
        tick_handler = timer_routine;
-       if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
-                       "timer 1", NULL))
+       if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, 0, "timer 1", NULL))
                pr_err("Couldn't register timer interrupt\n");
 
        /* Init the clock with a value */
index 0b28e26..31a66d9 100644 (file)
@@ -117,7 +117,7 @@ static void mvme16x_get_hardware_list(struct seq_file *m)
 
 static void __init mvme16x_init_IRQ (void)
 {
-       m68k_setup_user_interrupt(VEC_USER, 192, NULL);
+       m68k_setup_user_interrupt(VEC_USER, 192);
 }
 
 #define pcc2chip       ((volatile u_char *)0xfff42000)
index 9f0e3d5..2b88849 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
-#include <asm/irq.h>
 #include <asm/traps.h>
 
 #include <asm/q40_master.h>
 */
 
 static void q40_irq_handler(unsigned int, struct pt_regs *fp);
-static void q40_enable_irq(unsigned int);
-static void q40_disable_irq(unsigned int);
+static void q40_irq_enable(struct irq_data *data);
+static void q40_irq_disable(struct irq_data *data);
 
 unsigned short q40_ablecount[35];
 unsigned short q40_state[35];
 
-static int q40_irq_startup(unsigned int irq)
+static unsigned int q40_irq_startup(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        /* test for ISA ints not implemented by HW */
        switch (irq) {
        case 1: case 2: case 8: case 9:
        case 11: case 12: case 13:
                printk("%s: ISA IRQ %d not implemented by HW\n", __func__, irq);
-               return -ENXIO;
+               /* FIXME return -ENXIO; */
        }
        return 0;
 }
 
-static void q40_irq_shutdown(unsigned int irq)
+static void q40_irq_shutdown(struct irq_data *data)
 {
 }
 
-static struct irq_controller q40_irq_controller = {
+static struct irq_chip q40_irq_chip = {
        .name           = "q40",
-       .lock           = __SPIN_LOCK_UNLOCKED(q40_irq_controller.lock),
-       .startup        = q40_irq_startup,
-       .shutdown       = q40_irq_shutdown,
-       .enable         = q40_enable_irq,
-       .disable        = q40_disable_irq,
+       .irq_startup    = q40_irq_startup,
+       .irq_shutdown   = q40_irq_shutdown,
+       .irq_enable     = q40_irq_enable,
+       .irq_disable    = q40_irq_disable,
 };
 
 /*
@@ -81,13 +82,14 @@ static int disabled;
 
 void __init q40_init_IRQ(void)
 {
-       m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX);
+       m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1,
+                                 Q40_IRQ_MAX);
 
        /* setup handler for ISA ints */
        m68k_setup_auto_interrupt(q40_irq_handler);
 
-       m68k_irq_startup(IRQ_AUTO_2);
-       m68k_irq_startup(IRQ_AUTO_4);
+       m68k_irq_startup_irq(IRQ_AUTO_2);
+       m68k_irq_startup_irq(IRQ_AUTO_4);
 
        /* now enable some ints.. */
        master_outb(1, EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
@@ -218,11 +220,11 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
        switch (irq) {
        case 4:
        case 6:
-               __m68k_handle_int(Q40_IRQ_SAMPLE, fp);
+               do_IRQ(Q40_IRQ_SAMPLE, fp);
                return;
        }
        if (mir & Q40_IRQ_FRAME_MASK) {
-               __m68k_handle_int(Q40_IRQ_FRAME, fp);
+               do_IRQ(Q40_IRQ_FRAME, fp);
                master_outb(-1, FRAME_CLEAR_REG);
        }
        if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
@@ -257,7 +259,7 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
                                        goto iirq;
                                }
                                q40_state[irq] |= IRQ_INPROGRESS;
-                               __m68k_handle_int(irq, fp);
+                               do_IRQ(irq, fp);
                                q40_state[irq] &= ~IRQ_INPROGRESS;
 
                                /* naively enable everything, if that fails than    */
@@ -288,25 +290,29 @@ static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
        mir = master_inb(IIRQ_REG);
        /* should test whether keyboard irq is really enabled, doing it in defhand */
        if (mir & Q40_IRQ_KEYB_MASK)
-               __m68k_handle_int(Q40_IRQ_KEYBOARD, fp);
+               do_IRQ(Q40_IRQ_KEYBOARD, fp);
 
        return;
 }
 
-void q40_enable_irq(unsigned int irq)
+void q40_irq_enable(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        if (irq >= 5 && irq <= 15) {
                mext_disabled--;
                if (mext_disabled > 0)
-                       printk("q40_enable_irq : nested disable/enable\n");
+                       printk("q40_irq_enable : nested disable/enable\n");
                if (mext_disabled == 0)
                        master_outb(1, EXT_ENABLE_REG);
        }
 }
 
 
-void q40_disable_irq(unsigned int irq)
+void q40_irq_disable(struct irq_data *data)
 {
+       unsigned int irq = data->irq;
+
        /* disable ISA iqs : only do something if the driver has been
         * verified to be Q40 "compatible" - right now IDE, NE2K
         * Any driver should not attempt to sleep across disable_irq !!
@@ -319,13 +325,3 @@ void q40_disable_irq(unsigned int irq)
                        printk("disable_irq nesting count %d\n",mext_disabled);
        }
 }
-
-unsigned long q40_probe_irq_on(void)
-{
-       printk("irq probing not working - reconfigure the driver to avoid this\n");
-       return -1;
-}
-int q40_probe_irq_off(unsigned long irqs)
-{
-       return -1;
-}
index 6464ad3..78b60f5 100644 (file)
@@ -51,25 +51,29 @@ void sun3_disable_irq(unsigned int irq)
 
 static irqreturn_t sun3_int7(int irq, void *dev_id)
 {
-       *sun3_intreg |=  (1 << irq);
-       if (!(kstat_cpu(0).irqs[irq] % 2000))
-               sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 16000) / 2000]);
+       unsigned int cnt;
+
+       cnt = kstat_irqs_cpu(irq, 0);
+       if (!(cnt % 2000))
+               sun3_leds(led_pattern[cnt % 16000 / 2000]);
        return IRQ_HANDLED;
 }
 
 static irqreturn_t sun3_int5(int irq, void *dev_id)
 {
+       unsigned int cnt;
+
 #ifdef CONFIG_SUN3
        intersil_clear();
 #endif
-        *sun3_intreg |=  (1 << irq);
 #ifdef CONFIG_SUN3
        intersil_clear();
 #endif
        xtime_update(1);
        update_process_times(user_mode(get_irq_regs()));
-        if (!(kstat_cpu(0).irqs[irq] % 20))
-                sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
+       cnt = kstat_irqs_cpu(irq, 0);
+       if (!(cnt % 20))
+               sun3_leds(led_pattern[cnt % 160 / 20]);
        return IRQ_HANDLED;
 }
 
@@ -79,29 +83,33 @@ static irqreturn_t sun3_vec255(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static void sun3_inthandle(unsigned int irq, struct pt_regs *fp)
+static void sun3_irq_enable(struct irq_data *data)
 {
-        *sun3_intreg &= ~(1 << irq);
+    sun3_enable_irq(data->irq);
+};
 
-       __m68k_handle_int(irq, fp);
-}
+static void sun3_irq_disable(struct irq_data *data)
+{
+    sun3_disable_irq(data->irq);
+};
 
-static struct irq_controller sun3_irq_controller = {
+static struct irq_chip sun3_irq_chip = {
        .name           = "sun3",
-       .lock           = __SPIN_LOCK_UNLOCKED(sun3_irq_controller.lock),
-       .startup        = m68k_irq_startup,
-       .shutdown       = m68k_irq_shutdown,
-       .enable         = sun3_enable_irq,
-       .disable        = sun3_disable_irq,
+       .irq_startup    = m68k_irq_startup,
+       .irq_shutdown   = m68k_irq_shutdown,
+       .irq_enable     = sun3_irq_enable,
+       .irq_disable    = sun3_irq_disable,
+       .irq_mask       = sun3_irq_disable,
+       .irq_unmask     = sun3_irq_enable,
 };
 
 void __init sun3_init_IRQ(void)
 {
        *sun3_intreg = 1;
 
-       m68k_setup_auto_interrupt(sun3_inthandle);
-       m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
-       m68k_setup_user_interrupt(VEC_USER, 128, NULL);
+       m68k_setup_irq_controller(&sun3_irq_chip, handle_level_irq, IRQ_AUTO_1,
+                                 7);
+       m68k_setup_user_interrupt(VEC_USER, 128);
 
        if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
                pr_err("Couldn't register %s interrupt\n", "int5");
diff --git a/arch/microblaze/include/asm/namei.h b/arch/microblaze/include/asm/namei.h
deleted file mode 100644 (file)
index 61d60b8..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2006 Atmark Techno, Inc.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_MICROBLAZE_NAMEI_H
-#define _ASM_MICROBLAZE_NAMEI_H
-
-#ifdef __KERNEL__
-
-/* This dummy routine maybe changed to something useful
- * for /usr/gnemul/ emulation stuff.
- * Look at asm-sparc/namei.h for details.
- */
-#define __emul_prefix() NULL
-
-#endif /* __KERNEL__ */
-
-#endif /* _ASM_MICROBLAZE_NAMEI_H */
index 9b4cb00..0be3186 100644 (file)
@@ -286,11 +286,11 @@ CLEAN_FILES += vmlinux.32 vmlinux.64
 archprepare:
 ifdef CONFIG_MIPS32_N32
        @echo '  Checking missing-syscalls for N32'
-       $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32"
+       $(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=n32"
 endif
 ifdef CONFIG_MIPS32_O32
        @echo '  Checking missing-syscalls for O32'
-       $(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32"
+       $(Q)$(MAKE) $(build)=. missing-syscalls missing_syscalls_flags="-mabi=32"
 endif
 
 install:
index 975c203..0a430e0 100644 (file)
@@ -17,8 +17,6 @@
 
 static struct map_info flash_map;
 static struct mtd_info *mymtd;
-static int nr_parts;
-static struct mtd_partition *parts;
 static const char *part_probe_types[] = {
        "cmdlinepart",
 #ifdef CONFIG_MTD_REDBOOT_PARTS
@@ -61,11 +59,8 @@ static int __init flash_init(void)
                mymtd = do_map_probe("cfi_probe", &flash_map);
                if (mymtd) {
                        mymtd->owner = THIS_MODULE;
-
-                       nr_parts = parse_mtd_partitions(mymtd,
-                                                       part_probe_types,
-                                                       &parts, 0);
-                       mtd_device_register(mymtd, parts, nr_parts);
+                       mtd_device_parse_register(mymtd, part_probe_types,
+                                                 0, NULL, 0);
                } else {
                        pr_err("Failed to register MTD device for flash\n");
                }
index 8b60642..efcfff4 100644 (file)
@@ -207,8 +207,9 @@ void octeon_prepare_cpus(unsigned int max_cpus)
         * the other bits alone.
         */
        cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffff);
-       if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
-                       "SMP-IPI", mailbox_interrupt)) {
+       if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt,
+                       IRQF_PERCPU | IRQF_NO_THREAD, "SMP-IPI",
+                       mailbox_interrupt)) {
                panic("Cannot request_irq(OCTEON_IRQ_MBOX0)\n");
        }
 }
index 708f087..cae4225 100644 (file)
@@ -50,7 +50,7 @@ void __init prom_init(void)
 
        /* arg[0] is "g", the rest is boot parameters */
        for (i = 1; i < argc; i++) {
-               if (strlen(arcs_cmdline) + strlen(arg[i] + 1)
+               if (strlen(arcs_cmdline) + strlen(arg[i]) + 1
                    >= sizeof(arcs_cmdline))
                        break;
                strcat(arcs_cmdline, arg[i]);
index 76961ca..2ef17e8 100644 (file)
@@ -36,6 +36,8 @@ static inline int gpio_get_value(unsigned gpio)
        return -EINVAL;
 }
 
+#define gpio_get_value_cansleep        gpio_get_value
+
 static inline void gpio_set_value(unsigned gpio, int value)
 {
        switch (bcm47xx_bus_type) {
@@ -54,6 +56,19 @@ static inline void gpio_set_value(unsigned gpio, int value)
        }
 }
 
+#define gpio_set_value_cansleep gpio_set_value
+
+static inline int gpio_cansleep(unsigned gpio)
+{
+       return 0;
+}
+
+static inline int gpio_is_valid(unsigned gpio)
+{
+       return gpio < (BCM47XX_EXTIF_GPIO_LINES + BCM47XX_CHIPCO_GPIO_LINES);
+}
+
+
 static inline int gpio_direction_input(unsigned gpio)
 {
        switch (bcm47xx_bus_type) {
@@ -137,7 +152,4 @@ static inline int gpio_polarity(unsigned gpio, int value)
 }
 
 
-/* cansleep wrappers */
-#include <asm-generic/gpio.h>
-
 #endif /* __BCM47XX_GPIO_H */
index ecea787..d8dad53 100644 (file)
 #define __NR_syncfs                    (__NR_Linux + 342)
 #define __NR_sendmmsg                  (__NR_Linux + 343)
 #define __NR_setns                     (__NR_Linux + 344)
+#define __NR_process_vm_readv          (__NR_Linux + 345)
+#define __NR_process_vm_writev         (__NR_Linux + 346)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls            344
+#define __NR_Linux_syscalls            346
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux                 4000
-#define __NR_O32_Linux_syscalls                344
+#define __NR_O32_Linux_syscalls                346
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
 #define __NR_syncfs                    (__NR_Linux + 301)
 #define __NR_sendmmsg                  (__NR_Linux + 302)
 #define __NR_setns                     (__NR_Linux + 303)
+#define __NR_process_vm_readv          (__NR_Linux + 304)
+#define __NR_process_vm_writev         (__NR_Linux + 305)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls            303
+#define __NR_Linux_syscalls            305
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux                  5000
-#define __NR_64_Linux_syscalls         303
+#define __NR_64_Linux_syscalls         305
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
 #define __NR_syncfs                    (__NR_Linux + 306)
 #define __NR_sendmmsg                  (__NR_Linux + 307)
 #define __NR_setns                     (__NR_Linux + 308)
+#define __NR_process_vm_readv          (__NR_Linux + 309)
+#define __NR_process_vm_writev         (__NR_Linux + 310)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls            308
+#define __NR_Linux_syscalls            310
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux                 6000
-#define __NR_N32_Linux_syscalls                308
+#define __NR_N32_Linux_syscalls                310
 
 #ifdef __KERNEL__
 
index 98c5a97..e2d8e19 100644 (file)
@@ -103,19 +103,10 @@ static int c0_compare_int_pending(void)
 
 /*
  * Compare interrupt can be routed and latched outside the core,
- * so a single execution hazard barrier may not be enough to give
- * it time to clear as seen in the Cause register.  4 time the
- * pipeline depth seems reasonably conservative, and empirically
- * works better in configurations with high CPU/bus clock ratios.
+ * so wait up to worst case number of cycle counter ticks for timer interrupt
+ * changes to propagate to the cause register.
  */
-
-#define compare_change_hazard() \
-       do { \
-               irq_disable_hazard(); \
-               irq_disable_hazard(); \
-               irq_disable_hazard(); \
-               irq_disable_hazard(); \
-       } while (0)
+#define COMPARE_INT_SEEN_TICKS 50
 
 int c0_compare_int_usable(void)
 {
@@ -126,8 +117,12 @@ int c0_compare_int_usable(void)
         * IP7 already pending?  Try to clear it by acking the timer.
         */
        if (c0_compare_int_pending()) {
-               write_c0_compare(read_c0_count());
-               compare_change_hazard();
+               cnt = read_c0_count();
+               write_c0_compare(cnt);
+               back_to_back_c0_hazard();
+               while (read_c0_count() < (cnt  + COMPARE_INT_SEEN_TICKS))
+                       if (!c0_compare_int_pending())
+                               break;
                if (c0_compare_int_pending())
                        return 0;
        }
@@ -136,7 +131,7 @@ int c0_compare_int_usable(void)
                cnt = read_c0_count();
                cnt += delta;
                write_c0_compare(cnt);
-               compare_change_hazard();
+               back_to_back_c0_hazard();
                if ((int)(read_c0_count() - cnt) < 0)
                    break;
                /* increase delta if the timer was already expired */
@@ -145,12 +140,17 @@ int c0_compare_int_usable(void)
        while ((int)(read_c0_count() - cnt) <= 0)
                ;       /* Wait for expiry  */
 
-       compare_change_hazard();
+       while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+               if (c0_compare_int_pending())
+                       break;
        if (!c0_compare_int_pending())
                return 0;
-
-       write_c0_compare(read_c0_count());
-       compare_change_hazard();
+       cnt = read_c0_count();
+       write_c0_compare(cnt);
+       back_to_back_c0_hazard();
+       while (read_c0_count() < (cnt + COMPARE_INT_SEEN_TICKS))
+               if (!c0_compare_int_pending())
+                       break;
        if (c0_compare_int_pending())
                return 0;
 
index cefc6e2..5426779 100644 (file)
@@ -7,6 +7,7 @@
  * for more details.
  */
 
+#include <linux/module.h>
 #include <linux/cpufreq.h>
 #include <linux/platform_device.h>
 
index 4792065..a632bc1 100644 (file)
@@ -591,6 +591,8 @@ einval:     li      v0, -ENOSYS
        sys     sys_syncfs              1
        sys     sys_sendmmsg            4
        sys     sys_setns               2
+       sys     sys_process_vm_readv    6       /* 4345 */
+       sys     sys_process_vm_writev   6
        .endm
 
        /* We pre-compute the number of _instruction_ bytes needed to
index fb7334b..3b5a5e9 100644 (file)
@@ -430,4 +430,6 @@ sys_call_table:
        PTR     sys_syncfs
        PTR     sys_sendmmsg
        PTR     sys_setns
+       PTR     sys_process_vm_readv
+       PTR     sys_process_vm_writev           /* 5305 */
        .size   sys_call_table,.-sys_call_table
index 6de1f59..6be6f70 100644 (file)
@@ -430,4 +430,6 @@ EXPORT(sysn32_call_table)
        PTR     sys_syncfs
        PTR     compat_sys_sendmmsg
        PTR     sys_setns
+       PTR     compat_sys_process_vm_readv
+       PTR     compat_sys_process_vm_writev    /* 6310 */
        .size   sysn32_call_table,.-sysn32_call_table
index 1d81316..5422855 100644 (file)
@@ -548,4 +548,6 @@ sys_call_table:
        PTR     sys_syncfs
        PTR     compat_sys_sendmmsg
        PTR     sys_setns
+       PTR     compat_sys_process_vm_readv     /* 4345 */
+       PTR     compat_sys_process_vm_writev
        .size   sys_call_table,.-sys_call_table
index 261ccbc..5c8a49d 100644 (file)
@@ -1596,7 +1596,8 @@ void __cpuinit per_cpu_trap_init(void)
        }
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-       cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
+       if (!cpu_data[cpu].asid_cache)
+               cpu_data[cpu].asid_cache = ASID_FIRST_VERSION;
 
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
index 7e9c0ff..77ed70f 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
index 44a3677..de1cb2b 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
index 56ba007..e34fcfd 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
index 9b8af77..1ff6c9d 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <asm/bootinfo.h>
index 22d823a..6522583 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
index ddd3959..696b1a3 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 
index d0e32ab..d614aa7 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/mtd/physmap.h>
index 4278a45..cbb6ae5 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
+#include <linux/export.h>
 
 #include <lantiq_soc.h>
 #include <xway_dma.h>
index a321451..d2fa98f 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/slab.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/ioport.h>
index a479355..b91c7f1 100644 (file)
@@ -7,7 +7,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
index 67d59d6..ff9991c 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
index abe49f4..ae4959a 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
index 1686692..2228133 100644 (file)
@@ -6,7 +6,7 @@
  *  Copyright (C) 2010 John Crispin <blogic@openwrt.org>
  */
 
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <asm/bootinfo.h>
 #include <asm/time.h>
index a1be36d..3d41f0b 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/pm.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <asm/reboot.h>
 
 #include <lantiq_soc.h>
diff --git a/arch/mips/nxp/pnx8550/common/pci.c b/arch/mips/nxp/pnx8550/common/pci.c
deleted file mode 100644 (file)
index 98e86dd..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *
- * Author: source@mvista.com
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope 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/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <pci.h>
-#include <glb.h>
-#include <nand.h>
-
-static struct resource pci_io_resource = {
-       .start  = PNX8550_PCIIO + 0x1000,       /* reserve regacy I/O space */
-       .end    = PNX8550_PCIIO + PNX8550_PCIIO_SIZE,
-       .name   = "pci IO space",
-       .flags  = IORESOURCE_IO
-};
-
-static struct resource pci_mem_resource = {
-       .start  = PNX8550_PCIMEM,
-       .end    = PNX8550_PCIMEM + PNX8550_PCIMEM_SIZE - 1,
-       .name   = "pci memory space",
-       .flags  = IORESOURCE_MEM
-};
-
-extern struct pci_ops pnx8550_pci_ops;
-
-static struct pci_controller pnx8550_controller = {
-       .pci_ops        = &pnx8550_pci_ops,
-       .io_map_base    = PNX8550_PORT_BASE,
-       .io_resource    = &pci_io_resource,
-       .mem_resource   = &pci_mem_resource,
-};
-
-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
-static inline unsigned long get_system_mem_size(void)
-{
-       /* Read IP2031_RANK0_ADDR_LO */
-       unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
-       /* Read IP2031_RANK1_ADDR_HI */
-       unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
-
-       return dram_r1_hi - dram_r0_lo + 1;
-}
-
-static int __init pnx8550_pci_setup(void)
-{
-       int pci_mem_code;
-       int mem_size = get_system_mem_size() >> 20;
-
-       /* Clear the Global 2 Register, PCI Inta Output Enable Registers
-          Bit 1:Enable DAC Powerdown
-         -> 0:DACs are enabled and are working normally
-            1:DACs are powerdown
-          Bit 0:Enable of PCI inta output
-         -> 0 = Disable PCI inta output
-            1 = Enable PCI inta output
-       */
-       PNX8550_GLB2_ENAB_INTA_O = 0;
-
-       /* Calc the PCI mem size code */
-       if (mem_size >= 128)
-               pci_mem_code = SIZE_128M;
-       else if (mem_size >= 64)
-               pci_mem_code = SIZE_64M;
-       else if (mem_size >= 32)
-               pci_mem_code = SIZE_32M;
-       else
-               pci_mem_code = SIZE_16M;
-
-       /* Set PCI_XIO registers */
-       outl(pci_mem_resource.start, PCI_BASE | PCI_BASE1_LO);
-       outl(pci_mem_resource.end + 1, PCI_BASE | PCI_BASE1_HI);
-       outl(pci_io_resource.start, PCI_BASE | PCI_BASE2_LO);
-       outl(pci_io_resource.end, PCI_BASE | PCI_BASE2_HI);
-
-       /* Send memory transaction via PCI_BASE2 */
-       outl(0x00000001, PCI_BASE | PCI_IO);
-
-       /* Unlock the setup register */
-       outl(0xca, PCI_BASE | PCI_UNLOCKREG);
-
-       /*
-        * BAR0 of PNX8550 (pci base 10) must be zero in order for ide
-        * to work, and in order for bus_to_baddr to work without any
-        * hacks.
-        */
-       outl(0x00000000, PCI_BASE | PCI_BASE10);
-
-       /*
-        *These two bars are set by default or the boot code.
-        * However, it's safer to set them here so we're not boot
-        * code dependent.
-        */
-       outl(0x1be00000, PCI_BASE | PCI_BASE14);  /* PNX MMIO */
-       outl(PNX8550_NAND_BASE_ADDR, PCI_BASE | PCI_BASE18);  /* XIO      */
-
-       outl(PCI_EN_TA |
-            PCI_EN_PCI2MMI |
-            PCI_EN_XIO |
-            PCI_SETUP_BASE18_SIZE(SIZE_32M) |
-            PCI_SETUP_BASE18_EN |
-            PCI_SETUP_BASE14_EN |
-            PCI_SETUP_BASE10_PREF |
-            PCI_SETUP_BASE10_SIZE(pci_mem_code) |
-            PCI_SETUP_CFGMANAGE_EN |
-            PCI_SETUP_PCIARB_EN,
-            PCI_BASE |
-            PCI_SETUP);        /* PCI_SETUP */
-       outl(0x00000000, PCI_BASE | PCI_CTRL);  /* PCI_CONTROL */
-
-       register_pci_controller(&pnx8550_controller);
-
-       return 0;
-}
-
-arch_initcall(pnx8550_pci_setup);
diff --git a/arch/mips/nxp/pnx8550/common/setup.c b/arch/mips/nxp/pnx8550/common/setup.c
deleted file mode 100644 (file)
index 71adac3..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *
- * 2.6 port, Embedded Alley Solutions, Inc
- *
- *  Based on Per Hallsmark, per.hallsmark@mvista.com
- *
- *  This program is free software; you can distribute it and/or modify it
- *  under the terms of the GNU General Public License (Version 2) as
- *  published by the Free Software Foundation.
- *
- *  This program is distributed in the hope 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/init.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/irq.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/serial_pnx8xxx.h>
-#include <linux/pm.h>
-
-#include <asm/cpu.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
-#include <asm/reboot.h>
-#include <asm/pgtable.h>
-#include <asm/time.h>
-
-#include <glb.h>
-#include <int.h>
-#include <pci.h>
-#include <uart.h>
-#include <nand.h>
-
-extern void __init board_setup(void);
-extern void pnx8550_machine_restart(char *);
-extern void pnx8550_machine_halt(void);
-extern void pnx8550_machine_power_off(void);
-extern struct resource ioport_resource;
-extern struct resource iomem_resource;
-extern char *prom_getcmdline(void);
-
-struct resource standard_io_resources[] = {
-       {
-               .start  = 0x00,
-               .end    = 0x1f,
-               .name   = "dma1",
-               .flags  = IORESOURCE_BUSY
-       }, {
-               .start  = 0x40,
-               .end    = 0x5f,
-               .name   = "timer",
-               .flags  = IORESOURCE_BUSY
-       }, {
-               .start  = 0x80,
-               .end    = 0x8f,
-               .name   = "dma page reg",
-               .flags  = IORESOURCE_BUSY
-       }, {
-               .start  = 0xc0,
-               .end    = 0xdf,
-               .name   = "dma2",
-               .flags  = IORESOURCE_BUSY
-       },
-};
-
-#define STANDARD_IO_RESOURCES ARRAY_SIZE(standard_io_resources)
-
-extern struct resource pci_io_resource;
-extern struct resource pci_mem_resource;
-
-/* Return the total size of DRAM-memory, (RANK0 + RANK1) */
-unsigned long get_system_mem_size(void)
-{
-       /* Read IP2031_RANK0_ADDR_LO */
-       unsigned long dram_r0_lo = inl(PCI_BASE | 0x65010);
-       /* Read IP2031_RANK1_ADDR_HI */
-       unsigned long dram_r1_hi = inl(PCI_BASE | 0x65018);
-
-       return dram_r1_hi - dram_r0_lo + 1;
-}
-
-int pnx8550_console_port = -1;
-
-void __init plat_mem_setup(void)
-{
-       int i;
-       char* argptr;
-
-       board_setup();  /* board specific setup */
-
-        _machine_restart = pnx8550_machine_restart;
-        _machine_halt = pnx8550_machine_halt;
-        pm_power_off = pnx8550_machine_power_off;
-
-       /* Clear the Global 2 Register, PCI Inta Output Enable Registers
-          Bit 1:Enable DAC Powerdown
-         -> 0:DACs are enabled and are working normally
-            1:DACs are powerdown
-          Bit 0:Enable of PCI inta output
-         -> 0 = Disable PCI inta output
-            1 = Enable PCI inta output
-       */
-       PNX8550_GLB2_ENAB_INTA_O = 0;
-
-       /* IO/MEM resources. */
-       set_io_port_base(PNX8550_PORT_BASE);
-       ioport_resource.start = 0;
-       ioport_resource.end = ~0;
-       iomem_resource.start = 0;
-       iomem_resource.end = ~0;
-
-       /* Request I/O space for devices on this board */
-       for (i = 0; i < STANDARD_IO_RESOURCES; i++)
-               request_resource(&ioport_resource, standard_io_resources + i);
-
-       /* Place the Mode Control bit for GPIO pin 16 in primary function */
-       /* Pin 16 is used by UART1, UA1_TX                                */
-       outl((PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_16_BIT) |
-                       (PNX8550_GPIO_MODE_PRIMOP << PNX8550_GPIO_MC_17_BIT),
-                       PNX8550_GPIO_MC1);
-
-       argptr = prom_getcmdline();
-       if ((argptr = strstr(argptr, "console=ttyS")) != NULL) {
-               argptr += strlen("console=ttyS");
-               pnx8550_console_port = *argptr == '0' ? 0 : 1;
-
-               /* We must initialize the UART (console) before early printk */
-               /* Set LCR to 8-bit and BAUD to 38400 (no 5)                */
-               ip3106_lcr(UART_BASE, pnx8550_console_port) =
-                       PNX8XXX_UART_LCR_8BIT;
-               ip3106_baud(UART_BASE, pnx8550_console_port) = 5;
-       }
-}
index 4ee5710..b5ce041 100644 (file)
@@ -7,6 +7,7 @@
  * Support for all devices (greater than 16) added by David Gathright.
  */
 
+#include <linux/export.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
index 8656388..be1e1af 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/delay.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
+#include <linux/export.h>
 #include <linux/platform_device.h>
 
 #include <asm/pci.h>
index cf4c868..dcc926e 100644 (file)
@@ -102,7 +102,7 @@ void __init prom_init(void)
 
        /* Get the boot parameters */
        for (i = 1; i < argc; i++) {
-               if (strlen(arcs_cmdline) + strlen(arg[i] + 1) >=
+               if (strlen(arcs_cmdline) + strlen(arg[i]) + 1 >=
                    sizeof(arcs_cmdline))
                        break;
 
index b177caa..951e18f 100644 (file)
@@ -345,7 +345,7 @@ config ARCH_ENABLE_MEMORY_HOTREMOVE
 
 config KEXEC
        bool "kexec system call (EXPERIMENTAL)"
-       depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !47x)) && EXPERIMENTAL
+       depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP && !PPC_47x)) && EXPERIMENTAL
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel.  It is like a reboot
index 57af16e..70ba0c0 100644 (file)
@@ -255,12 +255,6 @@ checkbin:
                echo 'disable kernel modules' ; \
                false ; \
        fi
-       @if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \
-               echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \
-               echo 'correctly with old versions of binutils.' ; \
-               echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \
-               false ; \
-       fi
 
 CLEAN_FILES += $(TOUT)
 
diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
new file mode 100644 (file)
index 0000000..0e00e50
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * charon board Device Tree Source
+ *
+ * Copyright (C) 2007 Semihalf
+ * Marian Balakowicz <m8@semihalf.com>
+ *
+ * Copyright (C) 2010 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+       model = "anon,charon";
+       compatible = "anon,charon";
+       #address-cells = <1>;
+       #size-cells = <1>;
+       interrupt-parent = <&mpc5200_pic>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,5200@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       d-cache-line-size = <32>;
+                       i-cache-line-size = <32>;
+                       d-cache-size = <0x4000>;        // L1, 16K
+                       i-cache-size = <0x4000>;        // L1, 16K
+                       timebase-frequency = <0>;       // from bootloader
+                       bus-frequency = <0>;            // from bootloader
+                       clock-frequency = <0>;          // from bootloader
+               };
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x08000000>;  // 128MB
+       };
+
+       soc5200@f0000000 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,mpc5200-immr";
+               ranges = <0 0xf0000000 0x0000c000>;
+               reg = <0xf0000000 0x00000100>;
+               bus-frequency = <0>;            // from bootloader
+               system-frequency = <0>;         // from bootloader
+
+               cdm@200 {
+                       compatible = "fsl,mpc5200-cdm";
+                       reg = <0x200 0x38>;
+               };
+
+               mpc5200_pic: interrupt-controller@500 {
+                       // 5200 interrupts are encoded into two levels;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       compatible = "fsl,mpc5200-pic";
+                       reg = <0x500 0x80>;
+               };
+
+               timer@600 {     // General Purpose Timer
+                       compatible = "fsl,mpc5200-gpt";
+                       reg = <0x600 0x10>;
+                       interrupts = <1 9 0>;
+                       fsl,has-wdt;
+               };
+
+               can@900 {
+                       compatible = "fsl,mpc5200-mscan";
+                       interrupts = <2 17 0>;
+                       reg = <0x900 0x80>;
+               };
+
+               can@980 {
+                       compatible = "fsl,mpc5200-mscan";
+                       interrupts = <2 18 0>;
+                       reg = <0x980 0x80>;
+               };
+
+               gpio_simple: gpio@b00 {
+                       compatible = "fsl,mpc5200-gpio";
+                       reg = <0xb00 0x40>;
+                       interrupts = <1 7 0>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+
+               usb@1000 {
+                       compatible = "fsl,mpc5200-ohci","ohci-be";
+                       reg = <0x1000 0xff>;
+                       interrupts = <2 6 0>;
+               };
+
+               dma-controller@1200 {
+                       device_type = "dma-controller";
+                       compatible = "fsl,mpc5200-bestcomm";
+                       reg = <0x1200 0x80>;
+                       interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+                                     3 4 0  3 5 0  3 6 0  3 7 0
+                                     3 8 0  3 9 0  3 10 0  3 11 0
+                                     3 12 0  3 13 0  3 14 0  3 15 0>;
+               };
+
+               xlb@1f00 {
+                       compatible = "fsl,mpc5200-xlb";
+                       reg = <0x1f00 0x100>;
+               };
+
+               serial@2000 {           // PSC1
+                       compatible = "fsl,mpc5200-psc-uart";
+                       reg = <0x2000 0x100>;
+                       interrupts = <2 1 0>;
+               };
+
+               serial@2400 {           // PSC3
+                       compatible = "fsl,mpc5200-psc-uart";
+                       reg = <0x2400 0x100>;
+                       interrupts = <2 3 0>;
+               };
+
+               ethernet@3000 {
+                       compatible = "fsl,mpc5200-fec";
+                       reg = <0x3000 0x400>;
+                       local-mac-address = [ 00 00 00 00 00 00 ];
+                       interrupts = <2 5 0>;
+                       fixed-link = <1 1 100 0 0>;
+               };
+
+               mdio@3000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200-mdio";
+                       reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
+                       interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
+               };
+
+               ata@3a00 {
+                       compatible = "fsl,mpc5200-ata";
+                       reg = <0x3a00 0x100>;
+                       interrupts = <2 7 0>;
+               };
+
+               i2c@3d00 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200-i2c","fsl-i2c";
+                       reg = <0x3d00 0x40>;
+                       interrupts = <2 15 0>;
+               };
+
+
+               i2c@3d40 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "fsl,mpc5200-i2c","fsl-i2c";
+                       reg = <0x3d40 0x40>;
+                       interrupts = <2 16 0>;
+
+                       dtt@28 {
+                               compatible = "national,lm80";
+                               reg = <0x28>;
+                       };
+
+                       rtc@68 {
+                               compatible = "dallas,ds1374";
+                               reg = <0x68>;
+                       };
+               };
+
+               sram@8000 {
+                       compatible = "fsl,mpc5200-sram";
+                       reg = <0x8000 0x4000>;
+               };
+       };
+
+       localbus {
+               compatible = "fsl,mpc5200-lpb","simple-bus";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               ranges = <      0 0 0xfc000000 0x02000000
+                               1 0 0xe0000000 0x04000000 // CS1 range, SM501
+                               3 0 0xe8000000 0x00080000>;
+
+               flash@0,0 {
+                       compatible = "cfi-flash";
+                       reg = <0 0 0x02000000>;
+                       bank-width = <4>;
+                       device-width = <2>;
+                       #size-cells = <1>;
+                       #address-cells = <1>;
+               };
+
+               display@1,0 {
+                       compatible = "smi,sm501";
+                       reg = <1 0x00000000 0x00800000
+                              1 0x03e00000 0x00200000>;
+                       mode = "640x480-32@60";
+                       interrupts = <1 1 3>;
+                       little-endian;
+               };
+
+               mram0@3,0 {
+                       compatible = "mtd-ram";
+                       reg = <3 0x00000 0x80000>;
+                       bank-width = <1>;
+               };
+       };
+
+       pci@f0000d00 {
+               #interrupt-cells = <1>;
+               #size-cells = <2>;
+               #address-cells = <3>;
+               device_type = "pci";
+               compatible = "fsl,mpc5200-pci";
+               reg = <0xf0000d00 0x100>;
+               interrupt-map-mask = <0xf800 0 0 7>;
+               interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+                                0xc000 0 0 2 &mpc5200_pic 0 0 3
+                                0xc000 0 0 3 &mpc5200_pic 0 0 3
+                                0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+               clock-frequency = <0>; // From boot loader
+               interrupts = <2 8 0 2 9 0 2 10 0>;
+               bus-range = <0 0>;
+               ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+                         0x02000000 0 0x90000000 0x90000000 0 0x10000000
+                         0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+       };
+};
index d9b7767..d3b4782 100644 (file)
                        interrupt-parent = <&mpic>;
                        interrupts = <16 2>;
                        interrupt-map-mask = <0xf800 0 0 7>;
+                       /* IRQ[0:3] are pulled up on board, set to active-low */
                        interrupt-map = <
                                /* IDSEL 0x0 */
                                0000 0 0 1 &mpic 0 1
                        interrupt-parent = <&mpic>;
                        interrupts = <16 2>;
                        interrupt-map-mask = <0xf800 0 0 7>;
+                       /*
+                        * IRQ[4:6] only for PCIe, set to active-high,
+                        * IRQ[7] is pulled up on board, set to active-low
+                        */
                        interrupt-map = <
                                /* IDSEL 0x0 */
-                               0000 0 0 1 &mpic 4 1
-                               0000 0 0 2 &mpic 5 1
-                               0000 0 0 3 &mpic 6 1
+                               0000 0 0 1 &mpic 4 2
+                               0000 0 0 2 &mpic 5 2
+                               0000 0 0 3 &mpic 6 2
                                0000 0 0 4 &mpic 7 1
                                >;
                        ranges = <0x2000000 0x0 0xa0000000
                        interrupt-parent = <&mpic>;
                        interrupts = <16 2>;
                        interrupt-map-mask = <0xf800 0 0 7>;
+                       /*
+                        * IRQ[8:10] are pulled up on board, set to active-low
+                        * IRQ[11] only for PCIe, set to active-high,
+                        */
                        interrupt-map = <
                                /* IDSEL 0x0 */
                                0000 0 0 1 &mpic 8 1
                                0000 0 0 2 &mpic 9 1
                                0000 0 0 3 &mpic 10 1
-                               0000 0 0 4 &mpic 11 1
+                               0000 0 0 4 &mpic 11 2
                                >;
                        ranges = <0x2000000 0x0 0x80000000
                                  0x2000000 0x0 0x80000000
index 959cd2c..716a37b 100644 (file)
@@ -1,9 +1,10 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
@@ -17,7 +18,6 @@ CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_BESTCOMM=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -38,17 +38,18 @@ CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_MISC_DEVICES is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
@@ -56,13 +57,11 @@ CONFIG_PATA_MPC52xx=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_LXT_PHY=y
+CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_FEC_MPC52xx=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
 CONFIG_SERIAL_MPC52xx=y
 CONFIG_SERIAL_MPC52xx_CONSOLE=y
 CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
@@ -70,7 +69,13 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SENSORS_LM80=y
 CONFIG_WATCHDOG=y
+CONFIG_MFD_SM501=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_SM501=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
@@ -80,10 +85,10 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
@@ -102,7 +107,6 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index 6cdf1c0..3b98d73 100644 (file)
@@ -52,6 +52,8 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_JEDECPROBE=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_NAND=m
+CONFIG_MTD_NAND_NDFC=m
 CONFIG_MTD_UBI=m
 CONFIG_MTD_UBI_GLUEBI=m
 CONFIG_PROC_DEVICETREE=y
index 84a685a..535711f 100644 (file)
@@ -485,3 +485,7 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_VHOST_NET=m
index 96a58b7..a72f241 100644 (file)
@@ -362,3 +362,7 @@ CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
+CONFIG_VIRTUALIZATION=y
+CONFIG_KVM_BOOK3S_64=m
+CONFIG_KVM_BOOK3S_64_HV=y
+CONFIG_VHOST_NET=m
index e2a4c26..02e41b5 100644 (file)
@@ -49,13 +49,13 @@ static __inline__ int atomic_add_return(int a, atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%2         # atomic_add_return\n\
        add     %0,%1,%0\n"
        PPC405_ERR77(0,%2)
 "      stwcx.  %0,0,%2 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (a), "r" (&v->counter)
        : "cc", "memory");
@@ -85,13 +85,13 @@ static __inline__ int atomic_sub_return(int a, atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%2         # atomic_sub_return\n\
        subf    %0,%1,%0\n"
        PPC405_ERR77(0,%2)
 "      stwcx.  %0,0,%2 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (a), "r" (&v->counter)
        : "cc", "memory");
@@ -119,13 +119,13 @@ static __inline__ int atomic_inc_return(atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%1         # atomic_inc_return\n\
        addic   %0,%0,1\n"
        PPC405_ERR77(0,%1)
 "      stwcx.  %0,0,%1 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (&v->counter)
        : "cc", "xer", "memory");
@@ -163,13 +163,13 @@ static __inline__ int atomic_dec_return(atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%1         # atomic_dec_return\n\
        addic   %0,%0,-1\n"
        PPC405_ERR77(0,%1)
 "      stwcx.  %0,0,%1\n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (&v->counter)
        : "cc", "xer", "memory");
@@ -194,7 +194,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
        int t;
 
        __asm__ __volatile__ (
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%1         # __atomic_add_unless\n\
        cmpw    0,%0,%3 \n\
        beq-    2f \n\
@@ -202,7 +202,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
        PPC405_ERR77(0,%2)
 "      stwcx.  %0,0,%1 \n\
        bne-    1b \n"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
 "      subf    %0,%2,%0 \n\
 2:"
        : "=&r" (t)
@@ -226,7 +226,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
        int t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    lwarx   %0,0,%1         # atomic_dec_if_positive\n\
        cmpwi   %0,1\n\
        addi    %0,%0,-1\n\
@@ -234,7 +234,7 @@ static __inline__ int atomic_dec_if_positive(atomic_t *v)
        PPC405_ERR77(0,%1)
 "      stwcx.  %0,0,%1\n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        "\n\
 2:"    : "=&b" (t)
        : "r" (&v->counter)
@@ -285,12 +285,12 @@ static __inline__ long atomic64_add_return(long a, atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%2         # atomic64_add_return\n\
        add     %0,%1,%0\n\
        stdcx.  %0,0,%2 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (a), "r" (&v->counter)
        : "cc", "memory");
@@ -319,12 +319,12 @@ static __inline__ long atomic64_sub_return(long a, atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%2         # atomic64_sub_return\n\
        subf    %0,%1,%0\n\
        stdcx.  %0,0,%2 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (a), "r" (&v->counter)
        : "cc", "memory");
@@ -351,12 +351,12 @@ static __inline__ long atomic64_inc_return(atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%1         # atomic64_inc_return\n\
        addic   %0,%0,1\n\
        stdcx.  %0,0,%1 \n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (&v->counter)
        : "cc", "xer", "memory");
@@ -393,12 +393,12 @@ static __inline__ long atomic64_dec_return(atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%1         # atomic64_dec_return\n\
        addic   %0,%0,-1\n\
        stdcx.  %0,0,%1\n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        : "=&r" (t)
        : "r" (&v->counter)
        : "cc", "xer", "memory");
@@ -418,13 +418,13 @@ static __inline__ long atomic64_dec_if_positive(atomic64_t *v)
        long t;
 
        __asm__ __volatile__(
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%1         # atomic64_dec_if_positive\n\
        addic.  %0,%0,-1\n\
        blt-    2f\n\
        stdcx.  %0,0,%1\n\
        bne-    1b"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
        "\n\
 2:"    : "=&r" (t)
        : "r" (&v->counter)
@@ -450,14 +450,14 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
        long t;
 
        __asm__ __volatile__ (
-       PPC_RELEASE_BARRIER
+       PPC_ATOMIC_ENTRY_BARRIER
 "1:    ldarx   %0,0,%1         # __atomic_add_unless\n\
        cmpd    0,%0,%3 \n\
        beq-    2f \n\
        add     %0,%2,%0 \n"
 "      stdcx.  %0,0,%1 \n\
        bne-    1b \n"
-       PPC_ACQUIRE_BARRIER
+       PPC_ATOMIC_EXIT_BARRIER
 "      subf    %0,%2,%0 \n\
 2:"
        : "=&r" (t)
index e137afc..efdc926 100644 (file)
@@ -124,14 +124,14 @@ static __inline__ unsigned long fn(                       \
        return (old & mask);                            \
 }
 
-DEFINE_TESTOP(test_and_set_bits, or, PPC_RELEASE_BARRIER,
-             PPC_ACQUIRE_BARRIER, 0)
+DEFINE_TESTOP(test_and_set_bits, or, PPC_ATOMIC_ENTRY_BARRIER,
+             PPC_ATOMIC_EXIT_BARRIER, 0)
 DEFINE_TESTOP(test_and_set_bits_lock, or, "",
              PPC_ACQUIRE_BARRIER, 1)
-DEFINE_TESTOP(test_and_clear_bits, andc, PPC_RELEASE_BARRIER,
-             PPC_ACQUIRE_BARRIER, 0)
-DEFINE_TESTOP(test_and_change_bits, xor, PPC_RELEASE_BARRIER,
-             PPC_ACQUIRE_BARRIER, 0)
+DEFINE_TESTOP(test_and_clear_bits, andc, PPC_ATOMIC_ENTRY_BARRIER,
+             PPC_ATOMIC_EXIT_BARRIER, 0)
+DEFINE_TESTOP(test_and_change_bits, xor, PPC_ATOMIC_ENTRY_BARRIER,
+             PPC_ATOMIC_EXIT_BARRIER, 0)
 
 static __inline__ int test_and_set_bit(unsigned long nr,
                                       volatile unsigned long *addr)
index 24bd34c..936a904 100644 (file)
@@ -108,10 +108,10 @@ static int fd_request_irq(void)
 {
        if (can_use_virtual_dma)
                return request_irq(FLOPPY_IRQ, floppy_hardint,
-                                  IRQF_DISABLED, "floppy", NULL);
+                                  0, "floppy", NULL);
        else
                return request_irq(FLOPPY_IRQ, floppy_interrupt,
-                                  IRQF_DISABLED, "floppy", NULL);
+                                  0, "floppy", NULL);
 }
 
 static int vdma_dma_setup(char *addr, unsigned long size, int mode, int io)
index c94e4a3..2a9cf84 100644 (file)
 
 #define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
   __asm__ __volatile ( \
-       PPC_RELEASE_BARRIER \
+       PPC_ATOMIC_ENTRY_BARRIER \
 "1:    lwarx   %0,0,%2\n" \
        insn \
        PPC405_ERR77(0, %2) \
 "2:    stwcx.  %1,0,%2\n" \
        "bne-   1b\n" \
+       PPC_ATOMIC_EXIT_BARRIER \
        "li     %1,0\n" \
 "3:    .section .fixup,\"ax\"\n" \
 "4:    li      %1,%3\n" \
@@ -92,14 +93,14 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                return -EFAULT;
 
         __asm__ __volatile__ (
-        PPC_RELEASE_BARRIER
+        PPC_ATOMIC_ENTRY_BARRIER
 "1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
         cmpw    0,%1,%4\n\
         bne-    3f\n"
         PPC405_ERR77(0,%3)
 "2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
-        PPC_ACQUIRE_BARRIER
+        PPC_ATOMIC_EXIT_BARRIER
 "3:    .section .fixup,\"ax\"\n\
 4:     li      %0,%6\n\
        b       3b\n\
index 08fe69e..0ad432b 100644 (file)
@@ -148,12 +148,6 @@ struct kvm_regs {
 #define KVM_SREGS_E_UPDATE_DEC         (1 << 2)
 #define KVM_SREGS_E_UPDATE_DBSR                (1 << 3)
 
-/*
- * Book3S special bits to indicate contents in the struct by maintaining
- * backwards compatibility with older structs. If adding a new field,
- * please make sure to add a flag for that new field */
-#define KVM_SREGS_S_HIOR               (1 << 0)
-
 /*
  * In KVM_SET_SREGS, reserved/pad fields must be left untouched from a
  * previous KVM_GET_REGS.
@@ -179,8 +173,6 @@ struct kvm_sregs {
                                __u64 ibat[8]; 
                                __u64 dbat[8]; 
                        } ppc32;
-                       __u64 flags; /* KVM_SREGS_S_ */
-                       __u64 hior;
                } s;
                struct {
                        union {
index a384ffd..d4df013 100644 (file)
@@ -90,8 +90,6 @@ struct kvmppc_vcpu_book3s {
 #endif
        int context_id[SID_CONTEXTS];
 
-       bool hior_sregs;                /* HIOR is set by SREGS, not PVR */
-
        struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE];
        struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG];
        struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE];
index 9cd5fc8..f77c708 100644 (file)
@@ -316,7 +316,7 @@ LV1_CALL(gpu_context_free,                              1, 0, 218 )
 LV1_CALL(gpu_context_iomap,                             5, 0, 221 )
 LV1_CALL(gpu_context_attribute,                         6, 0, 225 )
 LV1_CALL(gpu_context_intr,                              1, 1, 227 )
-LV1_CALL(gpu_attribute,                                 5, 0, 228 )
+LV1_CALL(gpu_attribute,                                 3, 0, 228 )
 LV1_CALL(get_rtc,                                       0, 2, 232 )
 LV1_CALL(set_ppe_periodic_tracer_frequency,             1, 0, 240 )
 LV1_CALL(start_ppe_periodic_tracer,                     5, 0, 241 )
index 28cdbd9..03c48e8 100644 (file)
@@ -31,7 +31,7 @@
 
 #define MSR_           MSR_ME | MSR_CE
 #define MSR_KERNEL     MSR_ | MSR_64BIT
-#define MSR_USER32     MSR_ | MSR_PR | MSR_EE | MSR_DE
+#define MSR_USER32     MSR_ | MSR_PR | MSR_EE
 #define MSR_USER64     MSR_USER32 | MSR_64BIT
 #elif defined (CONFIG_40x)
 #define MSR_KERNEL     (MSR_ME|MSR_RI|MSR_IR|MSR_DR|MSR_CE)
index 6fbce72..a0f358d 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifdef __powerpc64__
 
-extern char _end[];
+extern char __end_interrupts[];
 
 static inline int in_kernel_text(unsigned long addr)
 {
index d7cab44..e682a71 100644 (file)
@@ -13,6 +13,7 @@
 extern unsigned int __start___lwsync_fixup, __stop___lwsync_fixup;
 extern void do_lwsync_fixups(unsigned long value, void *fixup_start,
                             void *fixup_end);
+extern void do_final_fixups(void);
 
 static inline void eieio(void)
 {
@@ -41,11 +42,15 @@ static inline void isync(void)
        START_LWSYNC_SECTION(97);                       \
        isync;                                          \
        MAKE_LWSYNC_SECTION_ENTRY(97, __lwsync_fixup);
-#define PPC_ACQUIRE_BARRIER    "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
-#define PPC_RELEASE_BARRIER    stringify_in_c(LWSYNC) "\n"
+#define PPC_ACQUIRE_BARRIER     "\n" stringify_in_c(__PPC_ACQUIRE_BARRIER)
+#define PPC_RELEASE_BARRIER     stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_ENTRY_BARRIER "\n" stringify_in_c(LWSYNC) "\n"
+#define PPC_ATOMIC_EXIT_BARRIER         "\n" stringify_in_c(sync) "\n"
 #else
 #define PPC_ACQUIRE_BARRIER
 #define PPC_RELEASE_BARRIER
+#define PPC_ATOMIC_ENTRY_BARRIER
+#define PPC_ATOMIC_EXIT_BARRIER
 #endif
 
 #endif /* __KERNEL__ */
index bd6c401..c48de98 100644 (file)
@@ -15,8 +15,8 @@
 #define        DEFAULT_PRIORITY        5
 
 /*
- * Mark IPIs as higher priority so we can take them inside interrupts that
- * arent marked IRQF_DISABLED
+ * Mark IPIs as higher priority so we can take them inside interrupts
+ * FIXME: still true now?
  */
 #define IPI_PRIORITY           4
 
index 56212bc..4f80cf1 100644 (file)
@@ -215,7 +215,22 @@ reenable_mmu:                              /* re-enable mmu so we can */
        stw     r9,8(r1)
        stw     r11,12(r1)
        stw     r3,ORIG_GPR3(r1)
+       /*
+        * The trace_hardirqs_off will use CALLER_ADDR0 and CALLER_ADDR1.
+        * If from user mode there is only one stack frame on the stack, and
+        * accessing CALLER_ADDR1 will cause oops. So we need create a dummy
+        * stack frame to make trace_hardirqs_off happy.
+        */
+       andi.   r12,r12,MSR_PR
+       beq     11f
+       stwu    r1,-16(r1)
+       bl      trace_hardirqs_off
+       addi    r1,r1,16
+       b       12f
+
+11:
        bl      trace_hardirqs_off
+12:
        lwz     r0,GPR0(r1)
        lwz     r3,ORIG_GPR3(r1)
        lwz     r4,GPR4(r1)
index a54d92f..cf9c69b 100644 (file)
@@ -267,7 +267,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
-       KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
 #endif /* CONFIG_CBE_RAS */
 
        STD_EXCEPTION_PSERIES(0x1300, 0x1300, instruction_breakpoint)
@@ -275,7 +275,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1600, 0x1602, cbe_maintenance)
-       KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1602)
 #endif /* CONFIG_CBE_RAS */
 
        STD_EXCEPTION_PSERIES(0x1700, 0x1700, altivec_assist)
@@ -283,7 +283,7 @@ vsx_unavailable_pSeries_1:
 
 #ifdef CONFIG_CBE_RAS
        STD_EXCEPTION_HV(0x1800, 0x1802, cbe_thermal)
-       KVM_HANDLER_PR_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
+       KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1802)
 #endif /* CONFIG_CBE_RAS */
 
        . = 0x3000
index 368d158..a1ed8a8 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/jump_label.h>
 #include <asm/code-patching.h>
 
+#ifdef HAVE_JUMP_LABEL
 void arch_jump_label_transform(struct jump_entry *entry,
                               enum jump_label_type type)
 {
@@ -21,3 +22,4 @@ void arch_jump_label_transform(struct jump_entry *entry,
        else
                patch_instruction(addr, PPC_INST_NOP);
 }
+#endif
index 35f2764..2985338 100644 (file)
@@ -132,7 +132,6 @@ static void kvm_patch_ins_b(u32 *inst, int addr)
        /* On relocatable kernels interrupts handlers and our code
           can be in different regions, so we don't patch them */
 
-       extern u32 __end_interrupts;
        if ((ulong)inst < (ulong)&__end_interrupts)
                return;
 #endif
index f7d760a..7cd07b4 100644 (file)
@@ -738,7 +738,7 @@ relocate_new_kernel:
        mr      r5, r31
 
        li      r0, 0
-#elif defined(CONFIG_44x)  && !defined(CONFIG_47x)
+#elif defined(CONFIG_44x)  && !defined(CONFIG_PPC_47x)
 
 /*
  * Code for setting up 1:1 mapping for PPC440x for KEXEC
index 9054ca9..6457574 100644 (file)
@@ -486,28 +486,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
        new_thread = &new->thread;
        old_thread = &current->thread;
 
-#if defined(CONFIG_PPC_BOOK3E_64)
-       /* XXX Current Book3E code doesn't deal with kernel side DBCR0,
-        * we always hold the user values, so we set it now.
-        *
-        * However, we ensure the kernel MSR:DE is appropriately cleared too
-        * to avoid spurrious single step exceptions in the kernel.
-        *
-        * This will have to change to merge with the ppc32 code at some point,
-        * but I don't like much what ppc32 is doing today so there's some
-        * thinking needed there
-        */
-       if ((new_thread->dbcr0 | old_thread->dbcr0) & DBCR0_IDM) {
-               u32 dbcr0;
-
-               mtmsr(mfmsr() & ~MSR_DE);
-               isync();
-               dbcr0 = mfspr(SPRN_DBCR0);
-               dbcr0 = (dbcr0 & DBCR0_EDM) | new_thread->dbcr0;
-               mtspr(SPRN_DBCR0, dbcr0);
-       }
-#endif /* CONFIG_PPC64_BOOK3E */
-
 #ifdef CONFIG_PPC64
        /*
         * Collect processor utilization data per process
@@ -657,7 +635,7 @@ void show_regs(struct pt_regs * regs)
        if ((regs->trap != 0xc00) && cpu_has_feature(CPU_FTR_CFAR))
                printk("CFAR: "REG"\n", regs->orig_gpr3);
        if (trap == 0x300 || trap == 0x600)
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
                printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
 #else
                printk("DAR: "REG", DSISR: %08lx\n", regs->dar, regs->dsisr);
index b4fa661..cc58486 100644 (file)
@@ -1579,10 +1579,8 @@ static void __init prom_instantiate_rtas(void)
                return;
 
        base = alloc_down(size, PAGE_SIZE, 0);
-       if (base == 0) {
-               prom_printf("RTAS allocation failed !\n");
-               return;
-       }
+       if (base == 0)
+               prom_panic("Could not allocate memory for RTAS\n");
 
        rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
        if (!IHANDLE_VALID(rtas_inst)) {
index c1ce863..ac76108 100644 (file)
@@ -107,6 +107,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
                         PTRRELOC(&__start___lwsync_fixup),
                         PTRRELOC(&__stop___lwsync_fixup));
 
+       do_final_fixups();
+
        return KERNELBASE + offset;
 }
 
index 1a9dea8..fb9bb46 100644 (file)
@@ -359,6 +359,7 @@ void __init setup_system(void)
                          &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup);
        do_lwsync_fixups(cur_cpu_spec->cpu_features,
                         &__start___lwsync_fixup, &__stop___lwsync_fixup);
+       do_final_fixups();
 
        /*
         * Unflatten the device-tree passed by prom_init or kexec
index 78b76dc..836a5a1 100644 (file)
@@ -97,7 +97,7 @@ static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set)
        compat_sigset_t cset;
 
        switch (_NSIG_WORDS) {
-       case 4: cset.sig[5] = set->sig[3] & 0xffffffffull;
+       case 4: cset.sig[6] = set->sig[3] & 0xffffffffull;
                cset.sig[7] = set->sig[3] >> 32;
        case 3: cset.sig[4] = set->sig[2] & 0xffffffffull;
                cset.sig[5] = set->sig[2] >> 32;
index 25ddbfc..6df7090 100644 (file)
@@ -187,7 +187,7 @@ int smp_request_message_ipi(int virq, int msg)
                return 1;
        }
 #endif
-       err = request_irq(virq, smp_ipi_action[msg], IRQF_DISABLED|IRQF_PERCPU,
+       err = request_irq(virq, smp_ipi_action[msg], IRQF_PERCPU,
                          smp_ipi_name[msg], 0);
        WARN(err < 0, "unable to request_irq %d for %s (rc %d)\n",
                virq, smp_ipi_name[msg], err);
index 4e59082..5459d14 100644 (file)
@@ -1298,14 +1298,12 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status)
 
                if (user_mode(regs)) {
                        current->thread.dbcr0 &= ~DBCR0_IC;
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
                        if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0,
                                               current->thread.dbcr1))
                                regs->msr |= MSR_DE;
                        else
                                /* Make sure the IDM bit is off */
                                current->thread.dbcr0 &= ~DBCR0_IDM;
-#endif
                }
 
                _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
index 0cdbc07..0cb137a 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/processor.h>
 #include <asm/cputhreads.h>
 #include <asm/page.h>
+#include <asm/hvcall.h>
 #include <linux/gfp.h>
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
index f422231..44d8829 100644 (file)
@@ -1263,7 +1263,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
        addi    r6,r5,VCORE_NAPPING_THREADS
 31:    lwarx   r4,0,r6
        or      r4,r4,r0
-       popcntw r7,r4
+       PPC_POPCNTW(r7,r4)
        cmpw    r7,r8
        bge     2f
        stwcx.  r4,0,r6
index bc4d50d..3c791e1 100644 (file)
@@ -151,16 +151,14 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr)
 #ifdef CONFIG_PPC_BOOK3S_64
        if ((pvr >= 0x330000) && (pvr < 0x70330000)) {
                kvmppc_mmu_book3s_64_init(vcpu);
-               if (!to_book3s(vcpu)->hior_sregs)
-                       to_book3s(vcpu)->hior = 0xfff00000;
+               to_book3s(vcpu)->hior = 0xfff00000;
                to_book3s(vcpu)->msr_mask = 0xffffffffffffffffULL;
                vcpu->arch.cpu_type = KVM_CPU_3S_64;
        } else
 #endif
        {
                kvmppc_mmu_book3s_32_init(vcpu);
-               if (!to_book3s(vcpu)->hior_sregs)
-                       to_book3s(vcpu)->hior = 0;
+               to_book3s(vcpu)->hior = 0;
                to_book3s(vcpu)->msr_mask = 0xffffffffULL;
                vcpu->arch.cpu_type = KVM_CPU_3S_32;
        }
@@ -797,9 +795,6 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
                }
        }
 
-       if (sregs->u.s.flags & KVM_SREGS_S_HIOR)
-               sregs->u.s.hior = to_book3s(vcpu)->hior;
-
        return 0;
 }
 
@@ -836,11 +831,6 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        /* Flush the MMU after messing with the segments */
        kvmppc_mmu_pte_flush(vcpu, 0, 0);
 
-       if (sregs->u.s.flags & KVM_SREGS_S_HIOR) {
-               to_book3s(vcpu)->hior_sregs = true;
-               to_book3s(vcpu)->hior = sregs->u.s.hior;
-       }
-
        return 0;
 }
 
index efbf9ad..607fbdf 100644 (file)
@@ -208,7 +208,6 @@ int kvm_dev_ioctl_check_extension(long ext)
        case KVM_CAP_PPC_BOOKE_SREGS:
 #else
        case KVM_CAP_PPC_SEGSTATE:
-       case KVM_CAP_PPC_HIOR:
        case KVM_CAP_PPC_PAPR:
 #endif
        case KVM_CAP_PPC_UNSET_IRQ:
index 0d08d01..7a8a748 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/init.h>
 #include <asm/cputable.h>
 #include <asm/code-patching.h>
+#include <asm/page.h>
+#include <asm/sections.h>
 
 
 struct fixup_entry {
@@ -128,6 +130,27 @@ void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end)
        }
 }
 
+void do_final_fixups(void)
+{
+#if defined(CONFIG_PPC64) && defined(CONFIG_RELOCATABLE)
+       int *src, *dest;
+       unsigned long length;
+
+       if (PHYSICAL_START == 0)
+               return;
+
+       src = (int *)(KERNELBASE + PHYSICAL_START);
+       dest = (int *)KERNELBASE;
+       length = (__end_interrupts - _stext) / sizeof(int);
+
+       while (length--) {
+               patch_instruction(dest, *src);
+               src++;
+               dest++;
+       }
+#endif
+}
+
 #ifdef CONFIG_FTR_FIXUP_SELFTEST
 
 #define check(x)       \
index 5964371..8558b57 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_fdt.h>
 #include <linux/memblock.h>
 #include <linux/bootmem.h>
+#include <linux/moduleparam.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/tlb.h>
index 16da595..2dd6bdd 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/suspend.h>
 #include <linux/memblock.h>
 #include <linux/hugetlb.h>
+#include <linux/slab.h>
 
 #include <asm/pgalloc.h>
 #include <asm/prom.h>
@@ -555,3 +556,32 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
                book3e_hugetlb_preload(vma->vm_mm, address, *ptep);
 #endif
 }
+
+/*
+ * System memory should not be in /proc/iomem but various tools expect it
+ * (eg kdump).
+ */
+static int add_system_ram_resources(void)
+{
+       struct memblock_region *reg;
+
+       for_each_memblock(memory, reg) {
+               struct resource *res;
+               unsigned long base = reg->base;
+               unsigned long size = reg->size;
+
+               res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+               WARN_ON(!res);
+
+               if (res) {
+                       res->name = "System RAM";
+                       res->start = base;
+                       res->end = base + size - 1;
+                       res->flags = IORESOURCE_MEM;
+                       WARN_ON(request_resource(&iomem_resource, res) < 0);
+               }
+       }
+
+       return 0;
+}
+subsys_initcall(add_system_ram_resources);
index c7dd4de..b22a83a 100644 (file)
@@ -315,7 +315,10 @@ static int __init find_min_common_depth(void)
        struct device_node *root;
        const char *vec5;
 
-       root = of_find_node_by_path("/rtas");
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               root = of_find_node_by_path("/ibm,opal");
+       else
+               root = of_find_node_by_path("/rtas");
        if (!root)
                root = of_find_node_by_path("/");
 
@@ -344,12 +347,19 @@ static int __init find_min_common_depth(void)
 
 #define VEC5_AFFINITY_BYTE     5
 #define VEC5_AFFINITY          0x80
-       chosen = of_find_node_by_path("/chosen");
-       if (chosen) {
-               vec5 = of_get_property(chosen, "ibm,architecture-vec-5", NULL);
-               if (vec5 && (vec5[VEC5_AFFINITY_BYTE] & VEC5_AFFINITY)) {
-                       dbg("Using form 1 affinity\n");
-                       form1_affinity = 1;
+
+       if (firmware_has_feature(FW_FEATURE_OPAL))
+               form1_affinity = 1;
+       else {
+               chosen = of_find_node_by_path("/chosen");
+               if (chosen) {
+                       vec5 = of_get_property(chosen,
+                                              "ibm,architecture-vec-5", NULL);
+                       if (vec5 && (vec5[VEC5_AFFINITY_BYTE] &
+                                                       VEC5_AFFINITY)) {
+                               dbg("Using form 1 affinity\n");
+                               form1_affinity = 1;
+                       }
                }
        }
 
index e36d6e2..846b789 100644 (file)
@@ -50,6 +50,7 @@ static void __init mpc5200_simple_setup_arch(void)
 
 /* list of the supported boards */
 static const char *board[] __initdata = {
+       "anon,charon",
        "intercontrol,digsy-mtc",
        "manroland,mucmc52",
        "manroland,uc101",
index 45023e2..d7946be 100644 (file)
@@ -203,7 +203,7 @@ config P3060_QDS
        select PPC_E500MC
        select PHYS_64BIT
        select SWIOTLB
-       select MPC8xxx_GPIO
+       select GPIO_MPC8XXX
        select HAS_RAPIDIO
        select PPC_EPAPR_HV_PIC
        help
index 01dcf44..081cf4a 100644 (file)
@@ -70,7 +70,7 @@ define_machine(p3060_qds) {
        .power_save             = e500_idle,
 };
 
-machine_device_initcall(p3060_qds, declare_of_platform_devices);
+machine_device_initcall(p3060_qds, corenet_ds_publish_devices);
 
 #ifdef CONFIG_SWIOTLB
 machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier);
index e458872..3fe6d92 100644 (file)
@@ -347,7 +347,7 @@ config SIMPLE_GPIO
 
 config MCU_MPC8349EMITX
        bool "MPC8349E-mITX MCU driver"
-       depends on I2C && PPC_83xx
+       depends on I2C=y && PPC_83xx
        select GENERIC_GPIO
        select ARCH_REQUIRE_GPIOLIB
        help
index 232fc38..852592b 100644 (file)
@@ -230,7 +230,7 @@ static int __init beat_register_event(void)
                }
                ev->virq = virq;
 
-               rc = request_irq(virq, ev->handler, IRQF_DISABLED,
+               rc = request_irq(virq, ev->handler, 0,
                                      ev->typecode, NULL);
                if (rc != 0) {
                        printk(KERN_ERR "Beat: failed to request virtual IRQ"
index ae790ac..14be2bd 100644 (file)
@@ -514,7 +514,7 @@ static __init int celleb_setup_pciex(struct device_node *node,
        virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
                                     oirq.size);
        if (request_irq(virq, pciex_handle_internal_irq,
-                       IRQF_DISABLED, "pciex", (void *)phb)) {
+                       0, "pciex", (void *)phb)) {
                pr_err("PCIEXC:Failed to request irq\n");
                goto error;
        }
index fc46fca..592c3d5 100644 (file)
@@ -412,8 +412,7 @@ static void cell_iommu_enable_hardware(struct cbe_iommu *iommu)
                        IIC_IRQ_IOEX_ATI | (iommu->nid << IIC_IRQ_NODE_SHIFT));
        BUG_ON(virq == NO_IRQ);
 
-       ret = request_irq(virq, ioc_interrupt, IRQF_DISABLED,
-                       iommu->name, iommu);
+       ret = request_irq(virq, ioc_interrupt, 0, iommu->name, iommu);
        BUG_ON(ret);
 
        /* set the IOC segment table origin register (and turn on the iommu) */
index 1acf360..59c1a16 100644 (file)
@@ -392,7 +392,7 @@ static int __init cbe_init_pm_irq(void)
                }
 
                rc = request_irq(irq, cbe_pm_irq,
-                                IRQF_DISABLED, "cbe-pmu-0", NULL);
+                                0, "cbe-pmu-0", NULL);
                if (rc) {
                        printk("ERROR: Request for irq on node %d failed\n",
                               node);
index 3675da7..e94d3ec 100644 (file)
@@ -442,8 +442,7 @@ static int spu_request_irqs(struct spu *spu)
                snprintf(spu->irq_c0, sizeof (spu->irq_c0), "spe%02d.0",
                         spu->number);
                ret = request_irq(spu->irqs[0], spu_irq_class_0,
-                                 IRQF_DISABLED,
-                                 spu->irq_c0, spu);
+                                 0, spu->irq_c0, spu);
                if (ret)
                        goto bail0;
        }
@@ -451,8 +450,7 @@ static int spu_request_irqs(struct spu *spu)
                snprintf(spu->irq_c1, sizeof (spu->irq_c1), "spe%02d.1",
                         spu->number);
                ret = request_irq(spu->irqs[1], spu_irq_class_1,
-                                 IRQF_DISABLED,
-                                 spu->irq_c1, spu);
+                                 0, spu->irq_c1, spu);
                if (ret)
                        goto bail1;
        }
@@ -460,8 +458,7 @@ static int spu_request_irqs(struct spu *spu)
                snprintf(spu->irq_c2, sizeof (spu->irq_c2), "spe%02d.2",
                         spu->number);
                ret = request_irq(spu->irqs[2], spu_irq_class_2,
-                                 IRQF_DISABLED,
-                                 spu->irq_c2, spu);
+                                 0, spu->irq_c2, spu);
                if (ret)
                        goto bail2;
        }
index cb40e92..901bfbd 100644 (file)
@@ -272,7 +272,6 @@ static struct irqaction xmon_action = {
 
 static struct irqaction gatwick_cascade_action = {
        .handler        = gatwick_action,
-       .flags          = IRQF_DISABLED,
        .name           = "cascade",
 };
 
index 9a521dc..9b6a820 100644 (file)
@@ -200,7 +200,7 @@ static int psurge_secondary_ipi_init(void)
 
        if (psurge_secondary_virq)
                rc = request_irq(psurge_secondary_virq, psurge_ipi_intr,
-                       IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
+                       IRQF_PERCPU, "IPI", NULL);
 
        if (rc)
                pr_err("Failed to setup secondary cpu IPI\n");
@@ -408,7 +408,7 @@ static int __init smp_psurge_kick_cpu(int nr)
 
 static struct irqaction psurge_irqaction = {
        .handler = psurge_ipi_intr,
-       .flags = IRQF_DISABLED|IRQF_PERCPU,
+       .flags = IRQF_PERCPU,
        .name = "primary IPI",
 };
 
index 6c4b583..3f175e8 100644 (file)
@@ -825,7 +825,7 @@ static int ps3_probe_thread(void *data)
 
        spin_lock_init(&dev.lock);
 
-       res = request_irq(irq, ps3_notification_interrupt, IRQF_DISABLED,
+       res = request_irq(irq, ps3_notification_interrupt, 0,
                          "ps3_notification", &dev);
        if (res) {
                pr_err("%s:%u: request_irq failed %d\n", __func__, __LINE__,
index 404bc52..1d6f4f4 100644 (file)
@@ -88,6 +88,7 @@ struct ps3_private {
        struct ps3_bmp bmp __attribute__ ((aligned (PS3_BMP_MINALIGN)));
        u64 ppe_id;
        u64 thread_id;
+       unsigned long ipi_mask;
 };
 
 static DEFINE_PER_CPU(struct ps3_private, ps3_private);
@@ -144,7 +145,11 @@ static void ps3_chip_unmask(struct irq_data *d)
 static void ps3_chip_eoi(struct irq_data *d)
 {
        const struct ps3_private *pd = irq_data_get_irq_chip_data(d);
-       lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
+
+       /* non-IPIs are EOIed here. */
+
+       if (!test_bit(63 - d->irq, &pd->ipi_mask))
+               lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
 }
 
 /**
@@ -691,6 +696,16 @@ void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq)
                cpu, virq, pd->bmp.ipi_debug_brk_mask);
 }
 
+void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq)
+{
+       struct ps3_private *pd = &per_cpu(ps3_private, cpu);
+
+       set_bit(63 - virq, &pd->ipi_mask);
+
+       DBG("%s:%d: cpu %u, virq %u, ipi_mask %lxh\n", __func__, __LINE__,
+               cpu, virq, pd->ipi_mask);
+}
+
 static unsigned int ps3_get_irq(void)
 {
        struct ps3_private *pd = &__get_cpu_var(ps3_private);
@@ -720,6 +735,12 @@ static unsigned int ps3_get_irq(void)
                BUG();
        }
 #endif
+
+       /* IPIs are EOIed here. */
+
+       if (test_bit(63 - plug, &pd->ipi_mask))
+               lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, plug);
+
        return plug;
 }
 
index 9a196a8..1a633ed 100644 (file)
@@ -43,6 +43,7 @@ void ps3_mm_shutdown(void);
 void ps3_init_IRQ(void);
 void ps3_shutdown_IRQ(int cpu);
 void __init ps3_register_ipi_debug_brk(unsigned int cpu, unsigned int virq);
+void __init ps3_register_ipi_irq(unsigned int cpu, unsigned int virq);
 
 /* smp */
 
index 5e304c2..ca40f6a 100644 (file)
@@ -184,7 +184,7 @@ int ps3_repository_read_bus_type(unsigned int bus_index,
        enum ps3_bus_type *bus_type)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -199,7 +199,7 @@ int ps3_repository_read_bus_num_dev(unsigned int bus_index,
        unsigned int *num_dev)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -239,7 +239,7 @@ int ps3_repository_read_dev_type(unsigned int bus_index,
        unsigned int dev_index, enum ps3_dev_type *dev_type)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -256,8 +256,8 @@ int ps3_repository_read_dev_intr(unsigned int bus_index,
        enum ps3_interrupt_type *intr_type, unsigned int *interrupt_id)
 {
        int result;
-       u64 v1;
-       u64 v2;
+       u64 v1 = 0;
+       u64 v2 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -275,7 +275,7 @@ int ps3_repository_read_dev_reg_type(unsigned int bus_index,
        enum ps3_reg_type *reg_type)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -615,7 +615,7 @@ int ps3_repository_read_stor_dev_num_regions(unsigned int bus_index,
        unsigned int dev_index, unsigned int *num_regions)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("bus", bus_index),
@@ -631,7 +631,7 @@ int ps3_repository_read_stor_dev_region_id(unsigned int bus_index,
        unsigned int *region_id)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
            make_first_field("bus", bus_index),
@@ -786,7 +786,7 @@ int ps3_repository_read_mm_info(u64 *rm_base, u64 *rm_size, u64 *region_total)
 int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -805,7 +805,7 @@ int ps3_repository_read_num_spu_reserved(unsigned int *num_spu_reserved)
 int ps3_repository_read_num_spu_resource_id(unsigned int *num_resource_id)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -827,8 +827,8 @@ int ps3_repository_read_spu_resource_id(unsigned int res_index,
        enum ps3_spu_resource_type *resource_type, unsigned int *resource_id)
 {
        int result;
-       u64 v1;
-       u64 v2;
+       u64 v1 = 0;
+       u64 v2 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -854,7 +854,7 @@ static int ps3_repository_read_boot_dat_address(u64 *address)
 int ps3_repository_read_boot_dat_size(unsigned int *size)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -869,7 +869,7 @@ int ps3_repository_read_boot_dat_size(unsigned int *size)
 int ps3_repository_read_vuart_av_port(unsigned int *port)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -884,7 +884,7 @@ int ps3_repository_read_vuart_av_port(unsigned int *port)
 int ps3_repository_read_vuart_sysmgr_port(unsigned int *port)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_CURRENT,
                make_first_field("bi", 0),
@@ -919,7 +919,7 @@ int ps3_repository_read_boot_dat_info(u64 *lpar_addr, unsigned int *size)
 int ps3_repository_read_num_be(unsigned int *num_be)
 {
        int result;
-       u64 v1;
+       u64 v1 = 0;
 
        result = read_node(PS3_LPAR_ID_PME,
                make_first_field("ben", 0),
index 4c44794..efc1cd8 100644 (file)
@@ -59,46 +59,49 @@ static void ps3_smp_message_pass(int cpu, int msg)
 
 static int ps3_smp_probe(void)
 {
-       return 2;
-}
+       int cpu;
 
-static void __init ps3_smp_setup_cpu(int cpu)
-{
-       int result;
-       unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
-       int i;
+       for (cpu = 0; cpu < 2; cpu++) {
+               int result;
+               unsigned int *virqs = per_cpu(ps3_ipi_virqs, cpu);
+               int i;
 
-       DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
+               DBG(" -> %s:%d: (%d)\n", __func__, __LINE__, cpu);
 
-       /*
-        * Check assumptions on ps3_ipi_virqs[] indexing. If this
-        * check fails, then a different mapping of PPC_MSG_
-        * to index needs to be setup.
-        */
+               /*
+               * Check assumptions on ps3_ipi_virqs[] indexing. If this
+               * check fails, then a different mapping of PPC_MSG_
+               * to index needs to be setup.
+               */
 
-       BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
-       BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
-       BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
-       BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
+               BUILD_BUG_ON(PPC_MSG_CALL_FUNCTION    != 0);
+               BUILD_BUG_ON(PPC_MSG_RESCHEDULE       != 1);
+               BUILD_BUG_ON(PPC_MSG_CALL_FUNC_SINGLE != 2);
+               BUILD_BUG_ON(PPC_MSG_DEBUGGER_BREAK   != 3);
 
-       for (i = 0; i < MSG_COUNT; i++) {
-               result = ps3_event_receive_port_setup(cpu, &virqs[i]);
+               for (i = 0; i < MSG_COUNT; i++) {
+                       result = ps3_event_receive_port_setup(cpu, &virqs[i]);
 
-               if (result)
-                       continue;
+                       if (result)
+                               continue;
 
-               DBG("%s:%d: (%d, %d) => virq %u\n",
-                       __func__, __LINE__, cpu, i, virqs[i]);
+                       DBG("%s:%d: (%d, %d) => virq %u\n",
+                               __func__, __LINE__, cpu, i, virqs[i]);
 
-               result = smp_request_message_ipi(virqs[i], i);
+                       result = smp_request_message_ipi(virqs[i], i);
 
-               if (result)
-                       virqs[i] = NO_IRQ;
-       }
+                       if (result)
+                               virqs[i] = NO_IRQ;
+                       else
+                               ps3_register_ipi_irq(cpu, virqs[i]);
+               }
 
-       ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
+               ps3_register_ipi_debug_brk(cpu, virqs[PPC_MSG_DEBUGGER_BREAK]);
 
-       DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
+               DBG(" <- %s:%d: (%d)\n", __func__, __LINE__, cpu);
+       }
+
+       return 2;
 }
 
 void ps3_smp_cleanup_cpu(int cpu)
@@ -121,7 +124,6 @@ static struct smp_ops_t ps3_smp_ops = {
        .probe          = ps3_smp_probe,
        .message_pass   = ps3_smp_message_pass,
        .kick_cpu       = smp_generic_kick_cpu,
-       .setup_cpu      = ps3_smp_setup_cpu,
 };
 
 void smp_init_ps3(void)
index af1a5df..b6731e4 100644 (file)
@@ -280,6 +280,7 @@ void __init ehv_pic_init(void)
 
        if (!ehv_pic->irqhost) {
                of_node_put(np);
+               kfree(ehv_pic);
                return;
        }
 
index c4d96fa..d5c3c90 100644 (file)
@@ -328,6 +328,7 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
 err:
        iounmap(fsl_lbc_ctrl_dev->regs);
        kfree(fsl_lbc_ctrl_dev);
+       fsl_lbc_ctrl_dev = NULL;
        return ret;
 }
 
index de170fd..22ffccd 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/export.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
index 0842c6f..8c7e852 100644 (file)
@@ -800,8 +800,6 @@ static void mpic_end_ipi(struct irq_data *d)
         * IPIs are marked IRQ_PER_CPU. This has the side effect of
         * preventing the IRQ_PENDING/IRQ_INPROGRESS logic from
         * applying to them. We EOI them late to avoid re-entering.
-        * We mark IPI's with IRQF_DISABLED as they must run with
-        * irqs disabled.
         */
        mpic_eoi(mpic);
 }
index d3d6ce3..0debcc3 100644 (file)
@@ -115,7 +115,7 @@ static int __init ppc4xx_l2c_probe(void)
        }
 
        /* Install error handler */
-       if (request_irq(irq, l2c_error_handler, IRQF_DISABLED, "L2C", 0) < 0) {
+       if (request_irq(irq, l2c_error_handler, 0, "L2C", 0) < 0) {
                printk(KERN_ERR "Cannot install L2C error handler"
                       ", cache is not enabled\n");
                of_node_put(np);
index 3363fbc..ceb09cb 100644 (file)
@@ -216,7 +216,7 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
        /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
           that the BRG divisor must be even if you're not using divide-by-16
           mode. */
-       if (!div16 && (divisor & 1))
+       if (!div16 && (divisor & 1) && (divisor > 3))
                divisor++;
 
        tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
index 3d93a8d..63762c6 100644 (file)
@@ -134,11 +134,10 @@ static void xics_request_ipi(void)
        BUG_ON(ipi == NO_IRQ);
 
        /*
-        * IPIs are marked IRQF_DISABLED as they must run with irqs
-        * disabled, and PERCPU.  The handler was set in map.
+        * IPIs are marked IRQF_PERCPU. The handler was set in map.
         */
        BUG_ON(request_irq(ipi, icp_ops->ipi_action,
-                          IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL));
+                          IRQF_PERCPU, "IPI", NULL));
 }
 
 int __init xics_smp_probe(void)
index a9fbd43..373679b 100644 (file)
@@ -572,6 +572,7 @@ config KEXEC
 config CRASH_DUMP
        bool "kernel crash dumps"
        depends on 64BIT
+       select KEXEC
        help
          Generate crash dump after being started by kexec.
          Crash dump kernels are loaded in the main kernel with kexec-tools
index 4967677..ffd1ac2 100644 (file)
@@ -368,9 +368,12 @@ static inline int crypt_s390_func_available(int func,
 
        if (facility_mask & CRYPT_S390_MSA && !test_facility(17))
                return 0;
-       if (facility_mask & CRYPT_S390_MSA3 && !test_facility(76))
+
+       if (facility_mask & CRYPT_S390_MSA3 &&
+           (!test_facility(2) || !test_facility(76)))
                return 0;
-       if (facility_mask & CRYPT_S390_MSA4 && !test_facility(77))
+       if (facility_mask & CRYPT_S390_MSA4 &&
+           (!test_facility(2) || !test_facility(77)))
                return 0;
 
        switch (func & CRYPT_S390_OP_MASK) {
index 24e1847..b0c235c 100644 (file)
@@ -47,7 +47,7 @@ struct sca_block {
 #define KVM_HPAGE_MASK(x)      (~(KVM_HPAGE_SIZE(x) - 1))
 #define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGE_SIZE)
 
-#define CPUSTAT_HOST       0x80000000
+#define CPUSTAT_STOPPED    0x80000000
 #define CPUSTAT_WAIT       0x10000000
 #define CPUSTAT_ECALL_PEND 0x08000000
 #define CPUSTAT_STOP_INT   0x04000000
@@ -139,6 +139,7 @@ struct kvm_vcpu_stat {
        u32 instruction_stfl;
        u32 instruction_tprot;
        u32 instruction_sigp_sense;
+       u32 instruction_sigp_sense_running;
        u32 instruction_sigp_external_call;
        u32 instruction_sigp_emergency;
        u32 instruction_sigp_stop;
index 34ede0e..524d23b 100644 (file)
@@ -593,6 +593,8 @@ static inline pgste_t pgste_update_all(pte_t *ptep, pgste_t pgste)
        unsigned long address, bits;
        unsigned char skey;
 
+       if (!pte_present(*ptep))
+               return pgste;
        address = pte_val(*ptep) & PAGE_MASK;
        skey = page_get_storage_key(address);
        bits = skey & (_PAGE_CHANGED | _PAGE_REFERENCED);
@@ -625,6 +627,8 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
 #ifdef CONFIG_PGSTE
        int young;
 
+       if (!pte_present(*ptep))
+               return pgste;
        young = page_reset_referenced(pte_val(*ptep) & PAGE_MASK);
        /* Transfer page referenced bit to pte software bit (host view) */
        if (young || (pgste_val(pgste) & RCP_HR_BIT))
@@ -638,13 +642,15 @@ static inline pgste_t pgste_update_young(pte_t *ptep, pgste_t pgste)
 
 }
 
-static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste)
+static inline void pgste_set_pte(pte_t *ptep, pgste_t pgste, pte_t entry)
 {
 #ifdef CONFIG_PGSTE
        unsigned long address;
        unsigned long okey, nkey;
 
-       address = pte_val(*ptep) & PAGE_MASK;
+       if (!pte_present(entry))
+               return;
+       address = pte_val(entry) & PAGE_MASK;
        okey = nkey = page_get_storage_key(address);
        nkey &= ~(_PAGE_ACC_BITS | _PAGE_FP_BIT);
        /* Set page access key and fetch protection bit from pgste */
@@ -712,7 +718,7 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 
        if (mm_has_pgste(mm)) {
                pgste = pgste_get_lock(ptep);
-               pgste_set_pte(ptep, pgste);
+               pgste_set_pte(ptep, pgste, entry);
                *ptep = entry;
                pgste_set_unlock(ptep, pgste);
        } else
index 5a09971..097183c 100644 (file)
@@ -82,6 +82,7 @@ extern unsigned int user_mode;
 #define MACHINE_FLAG_LPAR      (1UL << 12)
 #define MACHINE_FLAG_SPP       (1UL << 13)
 #define MACHINE_FLAG_TOPOLOGY  (1UL << 14)
+#define MACHINE_FLAG_STCKF     (1UL << 15)
 
 #define MACHINE_IS_VM          (S390_lowcore.machine_flags & MACHINE_FLAG_VM)
 #define MACHINE_IS_KVM         (S390_lowcore.machine_flags & MACHINE_FLAG_KVM)
@@ -100,6 +101,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF       (0)
 #define MACHINE_HAS_SPP                (0)
 #define MACHINE_HAS_TOPOLOGY   (0)
+#define MACHINE_HAS_STCKF      (0)
 #else /* __s390x__ */
 #define MACHINE_HAS_IEEE       (1)
 #define MACHINE_HAS_CSP                (1)
@@ -111,6 +113,7 @@ extern unsigned int user_mode;
 #define MACHINE_HAS_PFMF       (S390_lowcore.machine_flags & MACHINE_FLAG_PFMF)
 #define MACHINE_HAS_SPP                (S390_lowcore.machine_flags & MACHINE_FLAG_SPP)
 #define MACHINE_HAS_TOPOLOGY   (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
+#define MACHINE_HAS_STCKF      (S390_lowcore.machine_flags & MACHINE_FLAG_STCKF)
 #endif /* __s390x__ */
 
 #define ZFCPDUMP_HSA_SIZE      (32UL<<20)
index d610bef..c447a27 100644 (file)
@@ -90,7 +90,7 @@ static inline unsigned long long get_clock_fast(void)
 {
        unsigned long long clk;
 
-       if (test_facility(25))
+       if (MACHINE_HAS_STCKF)
                asm volatile(".insn     s,0xb27c0000,%0" : "=Q" (clk) : : "cc");
        else
                clk = get_clock();
index 404bdb9..58de4c9 100644 (file)
 #define __NR_clock_adjtime     337
 #define __NR_syncfs            338
 #define __NR_setns             339
-#define NR_syscalls 340
+#define __NR_process_vm_readv  340
+#define __NR_process_vm_writev 341
+#define NR_syscalls 342
 
 /* 
  * There are some system calls that are not present on 64 bit, some
index 5006a1d..18c51df 100644 (file)
@@ -1627,3 +1627,23 @@ ENTRY(sys_setns_wrapper)
        lgfr    %r2,%r2                 # int
        lgfr    %r3,%r3                 # int
        jg      sys_setns
+
+ENTRY(compat_sys_process_vm_readv_wrapper)
+       lgfr    %r2,%r2                 # compat_pid_t
+       llgtr   %r3,%r3                 # struct compat_iovec __user *
+       llgfr   %r4,%r4                 # unsigned long
+       llgtr   %r5,%r5                 # struct compat_iovec __user *
+       llgfr   %r6,%r6                 # unsigned long
+       llgf    %r0,164(%r15)           # unsigned long
+       stg     %r0,160(%r15)
+       jg      sys_process_vm_readv
+
+ENTRY(compat_sys_process_vm_writev_wrapper)
+       lgfr    %r2,%r2                 # compat_pid_t
+       llgtr   %r3,%r3                 # struct compat_iovec __user *
+       llgfr   %r4,%r4                 # unsigned long
+       llgtr   %r5,%r5                 # struct compat_iovec __user *
+       llgfr   %r6,%r6                 # unsigned long
+       llgf    %r0,164(%r15)           # unsigned long
+       stg     %r0,160(%r15)
+       jg      sys_process_vm_writev
index 37394b3..c9ffe00 100644 (file)
@@ -390,6 +390,8 @@ static __init void detect_machine_facilities(void)
                S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS;
        if (test_facility(40))
                S390_lowcore.machine_flags |= MACHINE_FLAG_SPP;
+       if (test_facility(25))
+               S390_lowcore.machine_flags |= MACHINE_FLAG_STCKF;
 #endif
 }
 
index 8ac6bfa..e58a462 100644 (file)
@@ -211,6 +211,8 @@ static void __init setup_zfcpdump(unsigned int console_devno)
 
        if (ipl_info.type != IPL_TYPE_FCP_DUMP)
                return;
+       if (OLDMEM_BASE)
+               return;
        if (console_devno != -1)
                sprintf(str, " cio_ignore=all,!0.0.%04x,!0.0.%04x",
                        ipl_info.data.fcp.dev_id.devno, console_devno);
@@ -482,7 +484,7 @@ static void __init setup_memory_end(void)
 
 
 #ifdef CONFIG_ZFCPDUMP
-       if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
+       if (ipl_info.type == IPL_TYPE_FCP_DUMP && !OLDMEM_BASE) {
                memory_end = ZFCPDUMP_HSA_SIZE;
                memory_end_set = 1;
        }
index 73eb08c..bcab2f0 100644 (file)
@@ -348,3 +348,5 @@ SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at
 SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper)
 SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
 SYSCALL(sys_setns,sys_setns,sys_setns_wrapper)
+SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */
+SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
index 77b8942..fdb5b8c 100644 (file)
@@ -68,8 +68,10 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
        return mask;
 }
 
-static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
-                            struct mask_info *book, struct mask_info *core)
+static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
+                                         struct mask_info *book,
+                                         struct mask_info *core,
+                                         int z10)
 {
        unsigned int cpu;
 
@@ -88,10 +90,16 @@ static void add_cpus_to_mask(struct topology_cpu *tl_cpu,
                        cpu_book_id[lcpu] = book->id;
 #endif
                        cpumask_set_cpu(lcpu, &core->mask);
-                       cpu_core_id[lcpu] = core->id;
+                       if (z10) {
+                               cpu_core_id[lcpu] = rcpu;
+                               core = core->next;
+                       } else {
+                               cpu_core_id[lcpu] = core->id;
+                       }
                        smp_cpu_polarization[lcpu] = tl_cpu->pp;
                }
        }
+       return core;
 }
 
 static void clear_masks(void)
@@ -123,18 +131,41 @@ static void tl_to_cores(struct sysinfo_15_1_x *info)
 {
 #ifdef CONFIG_SCHED_BOOK
        struct mask_info *book = &book_info;
+       struct cpuid cpu_id;
 #else
        struct mask_info *book = NULL;
 #endif
        struct mask_info *core = &core_info;
        union topology_entry *tle, *end;
+       int z10 = 0;
 
-
+#ifdef CONFIG_SCHED_BOOK
+       get_cpu_id(&cpu_id);
+       z10 = cpu_id.machine == 0x2097 || cpu_id.machine == 0x2098;
+#endif
        spin_lock_irq(&topology_lock);
        clear_masks();
        tle = info->tle;
        end = (union topology_entry *)((unsigned long)info + info->length);
        while (tle < end) {
+#ifdef CONFIG_SCHED_BOOK
+               if (z10) {
+                       switch (tle->nl) {
+                       case 1:
+                               book = book->next;
+                               book->id = tle->container.id;
+                               break;
+                       case 0:
+                               core = add_cpus_to_mask(&tle->cpu, book, core, z10);
+                               break;
+                       default:
+                               clear_masks();
+                               goto out;
+                       }
+                       tle = next_tle(tle);
+                       continue;
+               }
+#endif
                switch (tle->nl) {
 #ifdef CONFIG_SCHED_BOOK
                case 2:
@@ -147,7 +178,7 @@ static void tl_to_cores(struct sysinfo_15_1_x *info)
                        core->id = tle->container.id;
                        break;
                case 0:
-                       add_cpus_to_mask(&tle->cpu, book, core);
+                       add_cpus_to_mask(&tle->cpu, book, core, z10);
                        break;
                default:
                        clear_masks();
@@ -328,8 +359,8 @@ void __init s390_init_cpu_topology(void)
        for (i = 0; i < TOPOLOGY_NR_MAG; i++)
                printk(" %d", info->mag[i]);
        printk(" / %d\n", info->mnest);
-       alloc_masks(info, &core_info, 2);
+       alloc_masks(info, &core_info, 1);
 #ifdef CONFIG_SCHED_BOOK
-       alloc_masks(info, &book_info, 3);
+       alloc_masks(info, &book_info, 2);
 #endif
 }
index 56fe6bc..e4c79eb 100644 (file)
@@ -43,6 +43,8 @@ SECTIONS
 
        NOTES :text :note
 
+       .dummy : { *(.dummy) } :data
+
        RODATA
 
 #ifdef CONFIG_SHARED_KERNEL
index 87cedd6..8943e82 100644 (file)
@@ -70,7 +70,7 @@ static int __diag_ipl_functions(struct kvm_vcpu *vcpu)
                return -EOPNOTSUPP;
        }
 
-       atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+       atomic_set_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
        vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM;
        vcpu->run->s390_reset_flags |= KVM_S390_RESET_IPL;
        vcpu->run->s390_reset_flags |= KVM_S390_RESET_CPU_INIT;
index c7c5189..0243454 100644 (file)
@@ -132,7 +132,6 @@ static int handle_stop(struct kvm_vcpu *vcpu)
        int rc = 0;
 
        vcpu->stat.exit_stop_request++;
-       atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        spin_lock_bh(&vcpu->arch.local_int.lock);
        if (vcpu->arch.local_int.action_bits & ACTION_STORE_ON_STOP) {
                vcpu->arch.local_int.action_bits &= ~ACTION_STORE_ON_STOP;
@@ -149,6 +148,8 @@ static int handle_stop(struct kvm_vcpu *vcpu)
        }
 
        if (vcpu->arch.local_int.action_bits & ACTION_STOP_ON_STOP) {
+               atomic_set_mask(CPUSTAT_STOPPED,
+                               &vcpu->arch.sie_block->cpuflags);
                vcpu->arch.local_int.action_bits &= ~ACTION_STOP_ON_STOP;
                VCPU_EVENT(vcpu, 3, "%s", "cpu stopped");
                rc = -EOPNOTSUPP;
index 87c1670..278ee00 100644 (file)
@@ -252,6 +252,7 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu,
                        offsetof(struct _lowcore, restart_psw), sizeof(psw_t));
                if (rc == -EFAULT)
                        exception = 1;
+               atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
                break;
 
        case KVM_S390_PROGRAM_INT:
index 0bd3bea..d1c4457 100644 (file)
@@ -65,6 +65,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
        { "instruction_stfl", VCPU_STAT(instruction_stfl) },
        { "instruction_tprot", VCPU_STAT(instruction_tprot) },
        { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
+       { "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) },
        { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
        { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
        { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
@@ -127,6 +128,7 @@ int kvm_dev_ioctl_check_extension(long ext)
        switch (ext) {
        case KVM_CAP_S390_PSW:
        case KVM_CAP_S390_GMAP:
+       case KVM_CAP_SYNC_MMU:
                r = 1;
                break;
        default:
@@ -270,10 +272,12 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        restore_fp_regs(&vcpu->arch.guest_fpregs);
        restore_access_regs(vcpu->arch.guest_acrs);
        gmap_enable(vcpu->arch.gmap);
+       atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
 {
+       atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
        gmap_disable(vcpu->arch.gmap);
        save_fp_regs(&vcpu->arch.guest_fpregs);
        save_access_regs(vcpu->arch.guest_acrs);
@@ -301,7 +305,9 @@ static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-       atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
+       atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
+                                                   CPUSTAT_SM |
+                                                   CPUSTAT_STOPPED);
        vcpu->arch.sie_block->ecb   = 6;
        vcpu->arch.sie_block->eca   = 0xC1002001U;
        vcpu->arch.sie_block->fac   = (int) (long) facilities;
@@ -428,7 +434,7 @@ static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
 {
        int rc = 0;
 
-       if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
+       if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
                rc = -EBUSY;
        else {
                vcpu->run->psw_mask = psw.mask;
@@ -501,7 +507,7 @@ rerun_vcpu:
        if (vcpu->sigset_active)
                sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 
-       atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
+       atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
 
        BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
 
index 3916263..d026389 100644 (file)
@@ -336,6 +336,7 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
        u64 address1 = disp1 + base1 ? vcpu->arch.guest_gprs[base1] : 0;
        u64 address2 = disp2 + base2 ? vcpu->arch.guest_gprs[base2] : 0;
        struct vm_area_struct *vma;
+       unsigned long user_address;
 
        vcpu->stat.instruction_tprot++;
 
@@ -349,9 +350,14 @@ static int handle_tprot(struct kvm_vcpu *vcpu)
                return -EOPNOTSUPP;
 
 
+       /* we must resolve the address without holding the mmap semaphore.
+        * This is ok since the userspace hypervisor is not supposed to change
+        * the mapping while the guest queries the memory. Otherwise the guest
+        * might crash or get wrong info anyway. */
+       user_address = (unsigned long) __guestaddr_to_user(vcpu, address1);
+
        down_read(&current->mm->mmap_sem);
-       vma = find_vma(current->mm,
-                       (unsigned long) __guestaddr_to_user(vcpu, address1));
+       vma = find_vma(current->mm, user_address);
        if (!vma) {
                up_read(&current->mm->mmap_sem);
                return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
index f815118..0a7941d 100644 (file)
 #define SIGP_SET_PREFIX        0x0d
 #define SIGP_STORE_STATUS_ADDR 0x0e
 #define SIGP_SET_ARCH          0x12
+#define SIGP_SENSE_RUNNING     0x15
 
 /* cpu status bits */
 #define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
+#define SIGP_STAT_NOT_RUNNING      0x00000400UL
 #define SIGP_STAT_INCORRECT_STATE   0x00000200UL
 #define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
 #define SIGP_STAT_EXT_CALL_PENDING  0x00000080UL
@@ -57,8 +59,8 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
        spin_lock(&fi->lock);
        if (fi->local_int[cpu_addr] == NULL)
                rc = 3; /* not operational */
-       else if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
-                & CPUSTAT_RUNNING) {
+       else if (!(atomic_read(fi->local_int[cpu_addr]->cpuflags)
+                 & CPUSTAT_STOPPED)) {
                *reg &= 0xffffffff00000000UL;
                rc = 1; /* status stored */
        } else {
@@ -251,7 +253,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
 
        spin_lock_bh(&li->lock);
        /* cpu must be in stopped state */
-       if (atomic_read(li->cpuflags) & CPUSTAT_RUNNING) {
+       if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
                rc = 1; /* incorrect state */
                *reg &= SIGP_STAT_INCORRECT_STATE;
                kfree(inti);
@@ -275,6 +277,38 @@ out_fi:
        return rc;
 }
 
+static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
+                               unsigned long *reg)
+{
+       int rc;
+       struct kvm_s390_float_interrupt *fi = &vcpu->kvm->arch.float_int;
+
+       if (cpu_addr >= KVM_MAX_VCPUS)
+               return 3; /* not operational */
+
+       spin_lock(&fi->lock);
+       if (fi->local_int[cpu_addr] == NULL)
+               rc = 3; /* not operational */
+       else {
+               if (atomic_read(fi->local_int[cpu_addr]->cpuflags)
+                   & CPUSTAT_RUNNING) {
+                       /* running */
+                       rc = 1;
+               } else {
+                       /* not running */
+                       *reg &= 0xffffffff00000000UL;
+                       *reg |= SIGP_STAT_NOT_RUNNING;
+                       rc = 0;
+               }
+       }
+       spin_unlock(&fi->lock);
+
+       VCPU_EVENT(vcpu, 4, "sensed running status of cpu %x rc %x", cpu_addr,
+                  rc);
+
+       return rc;
+}
+
 int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
 {
        int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -331,6 +365,11 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
                rc = __sigp_set_prefix(vcpu, cpu_addr, parameter,
                                       &vcpu->arch.guest_gprs[r1]);
                break;
+       case SIGP_SENSE_RUNNING:
+               vcpu->stat.instruction_sigp_sense_running++;
+               rc = __sigp_sense_running(vcpu, cpu_addr,
+                                         &vcpu->arch.guest_gprs[r1]);
+               break;
        case SIGP_RESTART:
                vcpu->stat.instruction_sigp_restart++;
                /* user space must know about restart */
index 1766def..a9a3018 100644 (file)
@@ -587,8 +587,13 @@ static void pfault_interrupt(unsigned int ext_int_code,
                } else {
                        /* Completion interrupt was faster than initial
                         * interrupt. Set pfault_wait to -1 so the initial
-                        * interrupt doesn't put the task to sleep. */
-                       tsk->thread.pfault_wait = -1;
+                        * interrupt doesn't put the task to sleep.
+                        * If the task is not running, ignore the completion
+                        * interrupt since it must be a leftover of a PFAULT
+                        * CANCEL operation which didn't remove all pending
+                        * completion interrupts. */
+                       if (tsk->state == TASK_RUNNING)
+                               tsk->thread.pfault_wait = -1;
                }
                put_task_struct(tsk);
        } else {
index 0dca9a5..15d9703 100644 (file)
@@ -151,8 +151,13 @@ typedef struct page *pgtable_t;
 #endif /* !__ASSEMBLY__ */
 
 #ifdef CONFIG_UNCACHED_MAPPING
+#if defined(CONFIG_29BIT)
+#define UNCAC_ADDR(addr)       P2SEGADDR(addr)
+#define CAC_ADDR(addr)         P1SEGADDR(addr)
+#else
 #define UNCAC_ADDR(addr)       ((addr) - PAGE_OFFSET + uncached_start)
 #define CAC_ADDR(addr)         ((addr) - uncached_start + PAGE_OFFSET)
+#endif
 #else
 #define UNCAC_ADDR(addr)       ((addr))
 #define CAC_ADDR(addr)         ((addr))
index 3432008..152b862 100644 (file)
 #define __NR_syncfs            362
 #define __NR_sendmmsg          363
 #define __NR_setns             364
+#define __NR_process_vm_readv  365
+#define __NR_process_vm_writev 366
 
-#define NR_syscalls 365
+#define NR_syscalls 367
 
 #ifdef __KERNEL__
 
index ec98986..c330c23 100644 (file)
 #define __NR_syncfs            373
 #define __NR_sendmmsg          374
 #define __NR_setns             375
+#define __NR_process_vm_readv  376
+#define __NR_process_vm_writev 377
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 376
+#define NR_syscalls 378
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index a43124e..0bd744f 100644 (file)
@@ -176,10 +176,12 @@ static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups,
 static struct plat_sci_port scif0_platform_data = {
        .mapbase        = 0xfffe8000,
        .flags          = UPF_BOOT_AUTOCONF,
-       .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+       .scscr          = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+                         SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           =  { 192, 192, 192, 192 },
+       .regtype        = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif0_device = {
@@ -193,10 +195,12 @@ static struct platform_device scif0_device = {
 static struct plat_sci_port scif1_platform_data = {
        .mapbase        = 0xfffe8800,
        .flags          = UPF_BOOT_AUTOCONF,
-       .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+       .scscr          = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+                         SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           =  { 196, 196, 196, 196 },
+       .regtype        = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif1_device = {
@@ -210,10 +214,12 @@ static struct platform_device scif1_device = {
 static struct plat_sci_port scif2_platform_data = {
        .mapbase        = 0xfffe9000,
        .flags          = UPF_BOOT_AUTOCONF,
-       .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+       .scscr          = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+                         SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           =  { 200, 200, 200, 200 },
+       .regtype        = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif2_device = {
@@ -227,10 +233,12 @@ static struct platform_device scif2_device = {
 static struct plat_sci_port scif3_platform_data = {
        .mapbase        = 0xfffe9800,
        .flags          = UPF_BOOT_AUTOCONF,
-       .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_REIE,
+       .scscr          = SCSCR_RIE | SCSCR_TIE | SCSCR_RE | SCSCR_TE |
+                         SCSCR_REIE,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
        .irqs           =  { 204, 204, 204, 204 },
+       .regtype        = SCIx_SH2_SCIF_FIFODATA_REGTYPE,
 };
 
 static struct platform_device scif3_device = {
index 293e39c..ee56a9b 100644 (file)
@@ -382,3 +382,5 @@ ENTRY(sys_call_table)
        .long sys_syncfs
        .long sys_sendmmsg
        .long sys_setns
+       .long sys_process_vm_readv      /* 365 */
+       .long sys_process_vm_writev
index ceb34b9..9af7de2 100644 (file)
@@ -402,3 +402,5 @@ sys_call_table:
        .long sys_syncfs
        .long sys_sendmmsg
        .long sys_setns                 /* 375 */
+       .long sys_process_vm_readv
+       .long sys_process_vm_writev
index 5b31a8e..a790cc6 100644 (file)
@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_bitmap;
 #define kern_addr_valid(addr) \
        (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
 
-extern int io_remap_pfn_range(struct vm_area_struct *vma,
-                             unsigned long from, unsigned long pfn,
-                             unsigned long size, pgprot_t prot);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma,
 #define GET_IOSPACE(pfn)               (pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)                   (pfn & 0x0fffffffUL)
 
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+                          unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+                                    unsigned long from, unsigned long pfn,
+                                    unsigned long size, pgprot_t prot)
+{
+       unsigned long long offset, space, phys_base;
+
+       offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
+       space = GET_IOSPACE(pfn);
+       phys_base = offset | (space << 32ULL);
+
+       return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
 ({                                                                       \
index adf8932..38ebb2c 100644 (file)
@@ -757,10 +757,6 @@ static inline bool kern_addr_valid(unsigned long addr)
 
 extern int page_in_phys_avail(unsigned long paddr);
 
-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-                              unsigned long pfn,
-                              unsigned long size, pgprot_t prot);
-
 /*
  * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
  * its high 4 bits.  These macros/functions put it there or get it from there.
@@ -769,6 +765,22 @@ extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
 #define GET_IOSPACE(pfn)               (pfn >> (BITS_PER_LONG - 4))
 #define GET_PFN(pfn)                   (pfn & 0x0fffffffffffffffUL)
 
+extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
+                          unsigned long, pgprot_t);
+
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+                                    unsigned long from, unsigned long pfn,
+                                    unsigned long size, pgprot_t prot)
+{
+       unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+       int space = GET_IOSPACE(pfn);
+       unsigned long phys_base;
+
+       phys_base = offset | (((unsigned long) space) << 32UL);
+
+       return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
+}
+
 #include <asm-generic/pgtable.h>
 
 /* We provide our own get_unmapped_area to cope with VA holes and
index 6260d5d..c7cb0af 100644 (file)
 #define __NR_syncfs            335
 #define __NR_sendmmsg          336
 #define __NR_setns             337
+#define __NR_process_vm_readv  338
+#define __NR_process_vm_writev 339
 
-#define NR_syscalls            338
+#define NR_syscalls            340
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
index e27f8ea..0c218e4 100644 (file)
@@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 
 #else /* CONFIG_SPARC32 */
+
+#include <asm/trap_block.h>
+
 struct popc_3insn_patch_entry {
        unsigned int    addr;
        unsigned int    insns[3];
@@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __popc_6insn_patch,
        __popc_6insn_patch_end;
 
 extern void __init per_cpu_patch(void);
+extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
+                                   struct sun4v_1insn_patch_entry *);
+extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
+                                   struct sun4v_2insn_patch_entry *);
 extern void __init sun4v_patch(void);
 extern void __init boot_cpu_id_too_large(int cpu);
 extern unsigned int dcache_parity_tl1_occurred;
index da0c6c7..e551987 100644 (file)
@@ -17,6 +17,8 @@
 #include <asm/processor.h>
 #include <asm/spitfire.h>
 
+#include "entry.h"
+
 #ifdef CONFIG_SPARC64
 
 #include <linux/jump_label.h>
@@ -203,6 +205,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
 }
 
 #ifdef CONFIG_SPARC64
+static void do_patch_sections(const Elf_Ehdr *hdr,
+                             const Elf_Shdr *sechdrs)
+{
+       const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
+       char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+       for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
+               if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
+                       sun4v_1insn = s;
+               if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
+                       sun4v_2insn = s;
+       }
+
+       if (sun4v_1insn && tlb_type == hypervisor) {
+               void *p = (void *) sun4v_1insn->sh_addr;
+               sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
+       }
+       if (sun4v_2insn && tlb_type == hypervisor) {
+               void *p = (void *) sun4v_2insn->sh_addr;
+               sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
+       }
+}
+
 int module_finalize(const Elf_Ehdr *hdr,
                    const Elf_Shdr *sechdrs,
                    struct module *me)
@@ -210,6 +235,8 @@ int module_finalize(const Elf_Ehdr *hdr,
        /* make jump label nops */
        jump_label_apply_nops(me);
 
+       do_patch_sections(hdr, sechdrs);
+
        /* Cheetah's I-cache is fully coherent.  */
        if (tlb_type == spitfire) {
                unsigned long va;
index c965595..a854a1c 100644 (file)
@@ -234,40 +234,50 @@ void __init per_cpu_patch(void)
        }
 }
 
-void __init sun4v_patch(void)
+void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
+                            struct sun4v_1insn_patch_entry *end)
 {
-       extern void sun4v_hvapi_init(void);
-       struct sun4v_1insn_patch_entry *p1;
-       struct sun4v_2insn_patch_entry *p2;
-
-       if (tlb_type != hypervisor)
-               return;
+       while (start < end) {
+               unsigned long addr = start->addr;
 
-       p1 = &__sun4v_1insn_patch;
-       while (p1 < &__sun4v_1insn_patch_end) {
-               unsigned long addr = p1->addr;
-
-               *(unsigned int *) (addr +  0) = p1->insn;
+               *(unsigned int *) (addr +  0) = start->insn;
                wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
 
-               p1++;
+               start++;
        }
+}
 
-       p2 = &__sun4v_2insn_patch;
-       while (p2 < &__sun4v_2insn_patch_end) {
-               unsigned long addr = p2->addr;
+void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
+                            struct sun4v_2insn_patch_entry *end)
+{
+       while (start < end) {
+               unsigned long addr = start->addr;
 
-               *(unsigned int *) (addr +  0) = p2->insns[0];
+               *(unsigned int *) (addr +  0) = start->insns[0];
                wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  0));
 
-               *(unsigned int *) (addr +  4) = p2->insns[1];
+               *(unsigned int *) (addr +  4) = start->insns[1];
                wmb();
                __asm__ __volatile__("flush     %0" : : "r" (addr +  4));
 
-               p2++;
+               start++;
        }
+}
+
+void __init sun4v_patch(void)
+{
+       extern void sun4v_hvapi_init(void);
+
+       if (tlb_type != hypervisor)
+               return;
+
+       sun4v_patch_1insn_range(&__sun4v_1insn_patch,
+                               &__sun4v_1insn_patch_end);
+
+       sun4v_patch_2insn_range(&__sun4v_2insn_patch,
+                               &__sun4v_2insn_patch_end);
 
        sun4v_hvapi_init();
 }
index 2caa556..023b886 100644 (file)
@@ -822,21 +822,23 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-void do_signal32(sigset_t *oldset, struct pt_regs * regs,
-                int restart_syscall, unsigned long orig_i0)
+void do_signal32(sigset_t *oldset, struct pt_regs * regs)
 {
        struct k_sigaction ka;
+       unsigned long orig_i0;
+       int restart_syscall;
        siginfo_t info;
        int signr;
        
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-       /* If the debugger messes with the program counter, it clears
-        * the "in syscall" bit, directing us to not perform a syscall
-        * restart.
-        */
-       if (restart_syscall && !pt_regs_is_syscall(regs))
-               restart_syscall = 0;
+       restart_syscall = 0;
+       orig_i0 = 0;
+       if (pt_regs_is_syscall(regs) &&
+           (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+               restart_syscall = 1;
+               orig_i0 = regs->u_regs[UREG_G6];
+       }
 
        if (signr > 0) {
                if (restart_syscall)
index 8ce247a..d54c6e5 100644 (file)
@@ -519,10 +519,26 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        siginfo_t info;
        int signr;
 
+       /* It's a lot of work and synchronization to add a new ptrace
+        * register for GDB to save and restore in order to get
+        * orig_i0 correct for syscall restarts when debugging.
+        *
+        * Although it should be the case that most of the global
+        * registers are volatile across a system call, glibc already
+        * depends upon that fact that we preserve them.  So we can't
+        * just use any global register to save away the orig_i0 value.
+        *
+        * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+        * preserved across a system call trap by various pieces of
+        * code in glibc.
+        *
+        * %g7 is used as the "thread register".   %g6 is not used in
+        * any fixed manner.  %g6 is used as a scratch register and
+        * a compiler temporary, but it's value is never used across
+        * a system call.  Therefore %g6 is usable for orig_i0 storage.
+        */
        if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
-               restart_syscall = 1;
-       else
-               restart_syscall = 0;
+               regs->u_regs[UREG_G6] = orig_i0;
 
        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                oldset = &current->saved_sigmask;
@@ -535,8 +551,12 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
         * the software "in syscall" bit, directing us to not perform
         * a syscall restart.
         */
-       if (restart_syscall && !pt_regs_is_syscall(regs))
-               restart_syscall = 0;
+       restart_syscall = 0;
+       if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
+               restart_syscall = 1;
+               orig_i0 = regs->u_regs[UREG_G6];
+       }
+
 
        if (signr > 0) {
                if (restart_syscall)
index a2b8159..f0836cd 100644 (file)
@@ -529,11 +529,27 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        siginfo_t info;
        int signr;
        
+       /* It's a lot of work and synchronization to add a new ptrace
+        * register for GDB to save and restore in order to get
+        * orig_i0 correct for syscall restarts when debugging.
+        *
+        * Although it should be the case that most of the global
+        * registers are volatile across a system call, glibc already
+        * depends upon that fact that we preserve them.  So we can't
+        * just use any global register to save away the orig_i0 value.
+        *
+        * In particular %g2, %g3, %g4, and %g5 are all assumed to be
+        * preserved across a system call trap by various pieces of
+        * code in glibc.
+        *
+        * %g7 is used as the "thread register".   %g6 is not used in
+        * any fixed manner.  %g6 is used as a scratch register and
+        * a compiler temporary, but it's value is never used across
+        * a system call.  Therefore %g6 is usable for orig_i0 storage.
+        */
        if (pt_regs_is_syscall(regs) &&
-           (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
-               restart_syscall = 1;
-       } else
-               restart_syscall = 0;
+           (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
+               regs->u_regs[UREG_G6] = orig_i0;
 
        if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
@@ -542,22 +558,20 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
 
 #ifdef CONFIG_COMPAT
        if (test_thread_flag(TIF_32BIT)) {
-               extern void do_signal32(sigset_t *, struct pt_regs *,
-                                       int restart_syscall,
-                                       unsigned long orig_i0);
-               do_signal32(oldset, regs, restart_syscall, orig_i0);
+               extern void do_signal32(sigset_t *, struct pt_regs *);
+               do_signal32(oldset, regs);
                return;
        }
 #endif 
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
-       /* If the debugger messes with the program counter, it clears
-        * the software "in syscall" bit, directing us to not perform
-        * a syscall restart.
-        */
-       if (restart_syscall && !pt_regs_is_syscall(regs))
-               restart_syscall = 0;
+       restart_syscall = 0;
+       if (pt_regs_is_syscall(regs) &&
+           (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+               restart_syscall = 1;
+               orig_i0 = regs->u_regs[UREG_G6];
+       }
 
        if (signr > 0) {
                if (restart_syscall)
index e7dc508..b19570d 100644 (file)
@@ -2,6 +2,7 @@
 #include <linux/types.h>
 #include <linux/thread_info.h>
 #include <linux/uaccess.h>
+#include <linux/errno.h>
 
 #include <asm/sigcontext.h>
 #include <asm/fpumacro.h>
index 09d8ec4..63402f9 100644 (file)
@@ -84,4 +84,4 @@ sys_call_table:
 /*320*/        .long sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
 /*325*/        .long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
-/*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns
+/*335*/        .long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
index edbec45..db86b1a 100644 (file)
@@ -85,7 +85,7 @@ sys_call_table32:
 /*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, compat_sys_preadv
        .word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
-       .word sys_syncfs, compat_sys_sendmmsg, sys_setns
+       .word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
 
 #endif /* CONFIG_COMPAT */
 
@@ -162,4 +162,4 @@ sys_call_table:
 /*320*/        .word sys_dup3, sys_pipe2, sys_inotify_init1, sys_accept4, sys_preadv
        .word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/        .word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
-       .word sys_syncfs, sys_sendmmsg, sys_setns
+       .word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
index e3cda21..301421c 100644 (file)
@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64)   += ultra.o tlb.o tsb.o gup.o
 obj-y                   += fault_$(BITS).o
 obj-y                   += init_$(BITS).o
 obj-$(CONFIG_SPARC32)   += loadmmu.o
-obj-y                   += generic_$(BITS).o
 obj-$(CONFIG_SPARC32)   += extable.o btfixup.o srmmu.o iommu.o io-unit.o
 obj-$(CONFIG_SPARC32)   += hypersparc.o viking.o tsunami.o swift.o
 obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
diff --git a/arch/sparc/mm/generic_32.c b/arch/sparc/mm/generic_32.c
deleted file mode 100644 (file)
index 6ca39a6..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- *            MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/pagemap.h>
-#include <linux/export.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/cacheflush.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
-       unsigned long offset, pgprot_t prot, int space)
-{
-       unsigned long end;
-
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       do {
-               set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
-               address += PAGE_SIZE;
-               offset += PAGE_SIZE;
-               pte++;
-       } while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-       unsigned long offset, pgprot_t prot, int space)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       offset -= address;
-       do {
-               pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address < end);
-       return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-                      unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-       int error = 0;
-       pgd_t * dir;
-       unsigned long beg = from;
-       unsigned long end = from + size;
-       struct mm_struct *mm = vma->vm_mm;
-       int space = GET_IOSPACE(pfn);
-       unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-
-       /* See comment in mm/memory.c remap_pfn_range */
-       vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-       vma->vm_pgoff = (offset >> PAGE_SHIFT) |
-               ((unsigned long)space << 28UL);
-
-       offset -= from;
-       dir = pgd_offset(mm, from);
-       flush_cache_range(vma, beg, end);
-
-       while (from < end) {
-               pmd_t *pmd = pmd_alloc(mm, dir, from);
-               error = -ENOMEM;
-               if (!pmd)
-                       break;
-               error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
-               if (error)
-                       break;
-               from = (from + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       }
-
-       flush_tlb_range(vma, beg, end);
-       return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
diff --git a/arch/sparc/mm/generic_64.c b/arch/sparc/mm/generic_64.c
deleted file mode 100644 (file)
index 9b357dd..0000000
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * generic.c: Generic Sparc mm routines that are not dependent upon
- *            MMU type but are Sparc specific.
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/export.h>
-#include <linux/pagemap.h>
-
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/tlbflush.h>
-
-/* Remap IO memory, the same way as remap_pfn_range(), but use
- * the obio memory space.
- *
- * They use a pgprot that sets PAGE_IO and does not check the
- * mem_map table as this is independent of normal memory.
- */
-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
-                                     unsigned long address,
-                                     unsigned long size,
-                                     unsigned long offset, pgprot_t prot,
-                                     int space)
-{
-       unsigned long end;
-
-       /* clear hack bit that was used as a write_combine side-effect flag */
-       offset &= ~0x1UL;
-       address &= ~PMD_MASK;
-       end = address + size;
-       if (end > PMD_SIZE)
-               end = PMD_SIZE;
-       do {
-               pte_t entry;
-               unsigned long curend = address + PAGE_SIZE;
-               
-               entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
-               if (!(address & 0xffff)) {
-                       if (PAGE_SIZE < (4 * 1024 * 1024) &&
-                           !(address & 0x3fffff) &&
-                           !(offset & 0x3ffffe) &&
-                           end >= address + 0x400000) {
-                               entry = mk_pte_io(offset, prot, space,
-                                                 4 * 1024 * 1024);
-                               curend = address + 0x400000;
-                               offset += 0x400000;
-                       } else if (PAGE_SIZE < (512 * 1024) &&
-                                  !(address & 0x7ffff) &&
-                                  !(offset & 0x7fffe) &&
-                                  end >= address + 0x80000) {
-                               entry = mk_pte_io(offset, prot, space,
-                                                 512 * 1024 * 1024);
-                               curend = address + 0x80000;
-                               offset += 0x80000;
-                       } else if (PAGE_SIZE < (64 * 1024) &&
-                                  !(offset & 0xfffe) &&
-                                  end >= address + 0x10000) {
-                               entry = mk_pte_io(offset, prot, space,
-                                                 64 * 1024);
-                               curend = address + 0x10000;
-                               offset += 0x10000;
-                       } else
-                               offset += PAGE_SIZE;
-               } else
-                       offset += PAGE_SIZE;
-
-               if (pte_write(entry))
-                       entry = pte_mkdirty(entry);
-               do {
-                       BUG_ON(!pte_none(*pte));
-                       set_pte_at(mm, address, pte, entry);
-                       address += PAGE_SIZE;
-                       pte_val(entry) += PAGE_SIZE;
-                       pte++;
-               } while (address < curend);
-       } while (address < end);
-}
-
-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
-       unsigned long offset, pgprot_t prot, int space)
-{
-       unsigned long end;
-
-       address &= ~PGDIR_MASK;
-       end = address + size;
-       if (end > PGDIR_SIZE)
-               end = PGDIR_SIZE;
-       offset -= address;
-       do {
-               pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
-               if (!pte)
-                       return -ENOMEM;
-               io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
-               pte_unmap(pte);
-               address = (address + PMD_SIZE) & PMD_MASK;
-               pmd++;
-       } while (address < end);
-       return 0;
-}
-
-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
-       unsigned long offset, pgprot_t prot, int space)
-{
-       unsigned long end;
-
-       address &= ~PUD_MASK;
-       end = address + size;
-       if (end > PUD_SIZE)
-               end = PUD_SIZE;
-       offset -= address;
-       do {
-               pmd_t *pmd = pmd_alloc(mm, pud, address);
-               if (!pud)
-                       return -ENOMEM;
-               io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
-               address = (address + PUD_SIZE) & PUD_MASK;
-               pud++;
-       } while (address < end);
-       return 0;
-}
-
-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
-               unsigned long pfn, unsigned long size, pgprot_t prot)
-{
-       int error = 0;
-       pgd_t * dir;
-       unsigned long beg = from;
-       unsigned long end = from + size;
-       struct mm_struct *mm = vma->vm_mm;
-       int space = GET_IOSPACE(pfn);
-       unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
-       unsigned long phys_base;
-
-       phys_base = offset | (((unsigned long) space) << 32UL);
-
-       /* See comment in mm/memory.c remap_pfn_range */
-       vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
-       vma->vm_pgoff = phys_base >> PAGE_SHIFT;
-
-       offset -= from;
-       dir = pgd_offset(mm, from);
-       flush_cache_range(vma, beg, end);
-
-       while (from < end) {
-               pud_t *pud = pud_alloc(mm, dir, from);
-               error = -ENOMEM;
-               if (!pud)
-                       break;
-               error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
-               if (error)
-                       break;
-               from = (from + PGDIR_SIZE) & PGDIR_MASK;
-               dir++;
-       }
-
-       flush_tlb_range(vma, beg, end);
-       return error;
-}
-EXPORT_SYMBOL(io_remap_pfn_range);
index e57dcce..942ed61 100644 (file)
@@ -237,13 +237,13 @@ menu "PKUnity NetBook-0916 Features"
 
 config I2C_BATTERY_BQ27200
        tristate "I2C Battery BQ27200 Support"
-       select PUV3_I2C
+       select I2C_PUV3
        select POWER_SUPPLY
        select BATTERY_BQ27x00
 
 config I2C_EEPROM_AT24
        tristate "I2C EEPROMs AT24 support"
-       select PUV3_I2C
+       select I2C_PUV3
        select MISC_DEVICES
        select EEPROM_AT24
 
index ae2ec33..1a36262 100644 (file)
@@ -44,18 +44,4 @@ config DEBUG_OCD
          Say Y here if you want the debug print routines to direct their
          output to the UniCore On-Chip-Debugger channel using CP #1.
 
-config DEBUG_OCD_BREAKPOINT
-       bool "Breakpoint support via On-Chip-Debugger"
-       depends on DEBUG_OCD
-
-config DEBUG_UART
-       int "Kernel low-level debugging messages via serial port"
-       depends on DEBUG_LL
-       range 0 1
-       default "0"
-       help
-         Choice for UART for kernel low-level using PKUnity UARTS,
-         should be between zero and one. The port must have been
-         initialised by the boot-loader before use.
-
 endmenu
index b0954a2..950a9af 100644 (file)
@@ -10,8 +10,8 @@
 # Copyright (C) 2001~2010 GUAN Xue-tao
 #
 
-EXTRA_CFLAGS   := -fpic -fno-builtin
-EXTRA_AFLAGS   := -Wa,-march=all
+ccflags-y      := -fpic -fno-builtin
+asflags-y      := -Wa,-march=all
 
 OBJS           := misc.o
 
index 1628a63..401f597 100644 (file)
 #ifndef __UNICORE_BITOPS_H__
 #define __UNICORE_BITOPS_H__
 
-#define find_next_bit          __uc32_find_next_bit
-#define find_next_zero_bit     __uc32_find_next_zero_bit
-
-#define find_first_bit         __uc32_find_first_bit
-#define find_first_zero_bit    __uc32_find_first_zero_bit
-
 #define _ASM_GENERIC_BITOPS_FLS_H_
 #define _ASM_GENERIC_BITOPS___FLS_H_
 #define _ASM_GENERIC_BITOPS_FFS_H_
@@ -44,4 +38,10 @@ static inline int fls(int x)
 
 #include <asm-generic/bitops.h>
 
+/* following definitions: to avoid using codes in lib/find_*.c */
+#define find_next_bit          find_next_bit
+#define find_next_zero_bit     find_next_zero_bit
+#define find_first_bit         find_first_bit
+#define find_first_zero_bit    find_first_zero_bit
+
 #endif /* __UNICORE_BITOPS_H__ */
index e11cb07..f0d780a 100644 (file)
@@ -53,7 +53,6 @@ struct thread_struct {
 #define start_thread(regs, pc, sp)                                     \
 ({                                                                     \
        unsigned long *stack = (unsigned long *)sp;                     \
-       set_fs(USER_DS);                                                \
        memset(regs->uregs, 0, sizeof(regs->uregs));                    \
        regs->UCreg_asr = USER_MODE;                                    \
        regs->UCreg_pc = pc & ~1;       /* pc */                        \
index a897080..d98bd81 100644 (file)
@@ -24,8 +24,8 @@
 
 #include "ksyms.h"
 
-EXPORT_SYMBOL(__uc32_find_next_zero_bit);
-EXPORT_SYMBOL(__uc32_find_next_bit);
+EXPORT_SYMBOL(find_next_zero_bit);
+EXPORT_SYMBOL(find_next_bit);
 
 EXPORT_SYMBOL(__backtrace);
 
index c360ce9..c777462 100644 (file)
@@ -17,7 +17,7 @@
  * Purpose  : Find a 'zero' bit
  * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
  */
-__uc32_find_first_zero_bit:
+ENTRY(find_first_zero_bit)
                cxor.a  r1, #0
                beq     3f
                mov     r2, #0
@@ -29,13 +29,14 @@ __uc32_find_first_zero_bit:
                bub     1b
 3:             mov     r0, r1                  @ no free bits
                mov     pc, lr
+ENDPROC(find_first_zero_bit)
 
 /*
  * Purpose  : Find next 'zero' bit
  * Prototype: int find_next_zero_bit
  *             (void *addr, unsigned int maxbit, int offset)
  */
-ENTRY(__uc32_find_next_zero_bit)
+ENTRY(find_next_zero_bit)
                cxor.a  r1, #0
                beq     3b
                and.a   ip, r2, #7
@@ -47,14 +48,14 @@ ENTRY(__uc32_find_next_zero_bit)
                or      r2, r2, #7              @ if zero, then no bits here
                add     r2, r2, #1              @ align bit pointer
                b       2b                      @ loop for next bit
-ENDPROC(__uc32_find_next_zero_bit)
+ENDPROC(find_next_zero_bit)
 
 /*
  * Purpose  : Find a 'one' bit
  * Prototype: int find_first_bit
  *             (const unsigned long *addr, unsigned int maxbit);
  */
-__uc32_find_first_bit:
+ENTRY(find_first_bit)
                cxor.a  r1, #0
                beq     3f
                mov     r2, #0
@@ -66,13 +67,14 @@ __uc32_find_first_bit:
                bub     1b
 3:             mov     r0, r1                  @ no free bits
                mov     pc, lr
+ENDPROC(find_first_bit)
 
 /*
  * Purpose  : Find next 'one' bit
  * Prototype: int find_next_zero_bit
  *             (void *addr, unsigned int maxbit, int offset)
  */
-ENTRY(__uc32_find_next_bit)
+ENTRY(find_next_bit)
                cxor.a  r1, #0
                beq     3b
                and.a   ip, r2, #7
@@ -83,7 +85,7 @@ ENTRY(__uc32_find_next_bit)
                or      r2, r2, #7              @ if zero, then no bits here
                add     r2, r2, #1              @ align bit pointer
                b       2b                      @ loop for next bit
-ENDPROC(__uc32_find_next_bit)
+ENDPROC(find_next_bit)
 
 /*
  * One or more bits in the LSB of r3 are assumed to be set.
index 9b7273c..1a6c09a 100644 (file)
@@ -49,6 +49,7 @@ extern unsigned int apic_verbosity;
 extern int local_apic_timer_c2_ok;
 
 extern int disable_apic;
+extern unsigned int lapic_timer_frequency;
 
 #ifdef CONFIG_SMP
 extern void __inquire_remote_apic(int apicid);
index 72a8b52..a01e7ec 100644 (file)
@@ -17,7 +17,7 @@
 #define NMI_REASON_CLEAR_IOCHK 0x08
 #define NMI_REASON_CLEAR_MASK  0x0f
 
-static inline unsigned char get_nmi_reason(void)
+static inline unsigned char default_get_nmi_reason(void)
 {
        return inb(NMI_REASON_PORT);
 }
index c9321f3..0e8ae57 100644 (file)
@@ -201,7 +201,10 @@ int mce_notify_irq(void);
 void mce_notify_process(void);
 
 DECLARE_PER_CPU(struct mce, injectm);
-extern struct file_operations mce_chrdev_ops;
+
+extern void register_mce_write_callback(ssize_t (*)(struct file *filp,
+                                   const char __user *ubuf,
+                                   size_t usize, loff_t *off));
 
 /*
  * Exception handler
index 719f00b..e628312 100644 (file)
@@ -44,6 +44,13 @@ enum mrst_timer_options {
 
 extern enum mrst_timer_options mrst_timer_options;
 
+/*
+ * Penwell uses spread spectrum clock, so the freq number is not exactly
+ * the same as reported by MSR based on SDM.
+ */
+#define PENWELL_FSB_FREQ_83SKU         83200
+#define PENWELL_FSB_FREQ_100SKU        99840
+
 #define SFI_MTMR_MAX_NUM 8
 #define SFI_MRTC_MAX   8
 
index d3d8590..1971e65 100644 (file)
@@ -152,6 +152,7 @@ struct x86_cpuinit_ops {
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:             calibrate TSC
+ * @wallclock_init:            init the wallclock device
  * @get_wallclock:             get time from HW clock like RTC etc.
  * @set_wallclock:             set time back to HW clock
  * @is_untracked_pat_range     exclude from PAT logic
@@ -160,11 +161,13 @@ struct x86_cpuinit_ops {
  */
 struct x86_platform_ops {
        unsigned long (*calibrate_tsc)(void);
+       void (*wallclock_init)(void);
        unsigned long (*get_wallclock)(void);
        int (*set_wallclock)(unsigned long nowtime);
        void (*iommu_shutdown)(void);
        bool (*is_untracked_pat_range)(u64 start, u64 end);
        void (*nmi_init)(void);
+       unsigned char (*get_nmi_reason)(void);
        int (*i8042_detect)(void);
 };
 
index c638228..1f84794 100644 (file)
@@ -738,5 +738,5 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n)
 
        atomic_set(&stop_machine_first, 1);
        wrote_text = 0;
-       __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL);
+       __stop_machine(stop_machine_text_poke, (void *)&tpp, cpu_online_mask);
 }
index a2fd72e..f98d84c 100644 (file)
@@ -186,7 +186,7 @@ static struct resource lapic_resource = {
        .flags = IORESOURCE_MEM | IORESOURCE_BUSY,
 };
 
-static unsigned int calibration_result;
+unsigned int lapic_timer_frequency = 0;
 
 static void apic_pm_activate(void);
 
@@ -454,7 +454,7 @@ static void lapic_timer_setup(enum clock_event_mode mode,
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
        case CLOCK_EVT_MODE_ONESHOT:
-               __setup_APIC_LVTT(calibration_result,
+               __setup_APIC_LVTT(lapic_timer_frequency,
                                  mode != CLOCK_EVT_MODE_PERIODIC, 1);
                break;
        case CLOCK_EVT_MODE_UNUSED:
@@ -638,6 +638,25 @@ static int __init calibrate_APIC_clock(void)
        long delta, deltatsc;
        int pm_referenced = 0;
 
+       /**
+        * check if lapic timer has already been calibrated by platform
+        * specific routine, such as tsc calibration code. if so, we just fill
+        * in the clockevent structure and return.
+        */
+
+       if (lapic_timer_frequency) {
+               apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
+                               lapic_timer_frequency);
+               lapic_clockevent.mult = div_sc(lapic_timer_frequency/APIC_DIVISOR,
+                                       TICK_NSEC, lapic_clockevent.shift);
+               lapic_clockevent.max_delta_ns =
+                       clockevent_delta2ns(0x7FFFFF, &lapic_clockevent);
+               lapic_clockevent.min_delta_ns =
+                       clockevent_delta2ns(0xF, &lapic_clockevent);
+               lapic_clockevent.features &= ~CLOCK_EVT_FEAT_DUMMY;
+               return 0;
+       }
+
        local_irq_disable();
 
        /* Replace the global interrupt handler */
@@ -679,12 +698,12 @@ static int __init calibrate_APIC_clock(void)
        lapic_clockevent.min_delta_ns =
                clockevent_delta2ns(0xF, &lapic_clockevent);
 
-       calibration_result = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
+       lapic_timer_frequency = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
 
        apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
        apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
        apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
-                   calibration_result);
+                   lapic_timer_frequency);
 
        if (cpu_has_tsc) {
                apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
@@ -695,13 +714,13 @@ static int __init calibrate_APIC_clock(void)
 
        apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
                    "%u.%04u MHz.\n",
-                   calibration_result / (1000000 / HZ),
-                   calibration_result % (1000000 / HZ));
+                   lapic_timer_frequency / (1000000 / HZ),
+                   lapic_timer_frequency % (1000000 / HZ));
 
        /*
         * Do a sanity check on the APIC calibration result
         */
-       if (calibration_result < (1000000 / HZ)) {
+       if (lapic_timer_frequency < (1000000 / HZ)) {
                local_irq_enable();
                pr_warning("APIC frequency too slow, disabling apic timer\n");
                return -1;
index 3c31fa9..6d939d7 100644 (file)
@@ -193,10 +193,8 @@ int __init arch_early_irq_init(void)
        struct irq_cfg *cfg;
        int count, node, i;
 
-       if (!legacy_pic->nr_legacy_irqs) {
-               nr_irqs_gsi = 0;
+       if (!legacy_pic->nr_legacy_irqs)
                io_apic_irqs = ~0UL;
-       }
 
        for (i = 0; i < nr_ioapics; i++) {
                ioapics[i].saved_registers =
@@ -1696,6 +1694,7 @@ __apicdebuginit(void) print_IO_APICs(void)
        int ioapic_idx;
        struct irq_cfg *cfg;
        unsigned int irq;
+       struct irq_chip *chip;
 
        printk(KERN_DEBUG "number of MP IRQ sources: %d.\n", mp_irq_entries);
        for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++)
@@ -1716,6 +1715,10 @@ __apicdebuginit(void) print_IO_APICs(void)
        for_each_active_irq(irq) {
                struct irq_pin_list *entry;
 
+               chip = irq_get_chip(irq);
+               if (chip != &ioapic_chip)
+                       continue;
+
                cfg = irq_get_chip_data(irq);
                if (!cfg)
                        continue;
index 6199232..319882e 100644 (file)
@@ -208,7 +208,7 @@ static int inject_init(void)
        if (!alloc_cpumask_var(&mce_inject_cpumask, GFP_KERNEL))
                return -ENOMEM;
        printk(KERN_INFO "Machine check injector initialized\n");
-       mce_chrdev_ops.write = mce_write;
+       register_mce_write_callback(mce_write);
        register_nmi_handler(NMI_LOCAL, mce_raise_notify, 0,
                                "mce_notify");
        return 0;
index 362056a..2af127d 100644 (file)
@@ -1634,16 +1634,35 @@ static long mce_chrdev_ioctl(struct file *f, unsigned int cmd,
        }
 }
 
-/* Modified in mce-inject.c, so not static or const */
-struct file_operations mce_chrdev_ops = {
+static ssize_t (*mce_write)(struct file *filp, const char __user *ubuf,
+                           size_t usize, loff_t *off);
+
+void register_mce_write_callback(ssize_t (*fn)(struct file *filp,
+                            const char __user *ubuf,
+                            size_t usize, loff_t *off))
+{
+       mce_write = fn;
+}
+EXPORT_SYMBOL_GPL(register_mce_write_callback);
+
+ssize_t mce_chrdev_write(struct file *filp, const char __user *ubuf,
+                        size_t usize, loff_t *off)
+{
+       if (mce_write)
+               return mce_write(filp, ubuf, usize, off);
+       else
+               return -EINVAL;
+}
+
+static const struct file_operations mce_chrdev_ops = {
        .open                   = mce_chrdev_open,
        .release                = mce_chrdev_release,
        .read                   = mce_chrdev_read,
+       .write                  = mce_chrdev_write,
        .poll                   = mce_chrdev_poll,
        .unlocked_ioctl         = mce_chrdev_ioctl,
        .llseek                 = no_llseek,
 };
-EXPORT_SYMBOL_GPL(mce_chrdev_ops);
 
 static struct miscdevice mce_chrdev_device = {
        MISC_MCELOG_MINOR,
index c1a0188..44842d7 100644 (file)
@@ -74,9 +74,10 @@ static cycle_t kvm_clock_read(void)
        struct pvclock_vcpu_time_info *src;
        cycle_t ret;
 
-       src = &get_cpu_var(hv_clock);
+       preempt_disable_notrace();
+       src = &__get_cpu_var(hv_clock);
        ret = pvclock_clocksource_read(src);
-       put_cpu_var(hv_clock);
+       preempt_enable_notrace();
        return ret;
 }
 
index b9c8628..e88f37b 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/traps.h>
 #include <asm/mach_traps.h>
 #include <asm/nmi.h>
+#include <asm/x86_init.h>
 
 #define NMI_MAX_NAMELEN        16
 struct nmiaction {
@@ -348,7 +349,7 @@ static notrace __kprobes void default_do_nmi(struct pt_regs *regs)
 
        /* Non-CPU-specific NMI: NMI sources can be processed on any CPU */
        raw_spin_lock(&nmi_reason_lock);
-       reason = get_nmi_reason();
+       reason = x86_platform.get_nmi_reason();
 
        if (reason & NMI_REASON_MASK) {
                if (reason & NMI_REASON_SERR)
index afaf384..cf0ef98 100644 (file)
@@ -1045,6 +1045,8 @@ void __init setup_arch(char **cmdline_p)
 
        x86_init.timers.wallclock_init();
 
+       x86_platform.wallclock_init();
+
        mcheck_init();
 
        arch_init_ideal_nops();
index 6f164bd..c1d6cd5 100644 (file)
 #include <asm/pat.h>
 #include <asm/tsc.h>
 #include <asm/iommu.h>
+#include <asm/mach_traps.h>
 
 void __cpuinit x86_init_noop(void) { }
 void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
+void wallclock_init_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -97,11 +99,13 @@ static int default_i8042_detect(void) { return 1; };
 
 struct x86_platform_ops x86_platform = {
        .calibrate_tsc                  = native_calibrate_tsc,
+       .wallclock_init                 = wallclock_init_noop,
        .get_wallclock                  = mach_get_cmos_time,
        .set_wallclock                  = mach_set_rtc_mmss,
        .iommu_shutdown                 = iommu_shutdown_noop,
        .is_untracked_pat_range         = is_ISA_range,
        .nmi_init                       = default_nmi_init,
+       .get_nmi_reason                 = default_get_nmi_reason,
        .i8042_detect                   = default_i8042_detect
 };
 
index a0d6bd9..579a0b5 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/mce.h>
 #include <asm/i387.h>
 #include <asm/xcr.h>
+#include <asm/perf_event.h>
 
 #include "trace.h"
 
@@ -118,7 +119,7 @@ module_param(ple_gap, int, S_IRUGO);
 static int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
 module_param(ple_window, int, S_IRUGO);
 
-#define NR_AUTOLOAD_MSRS 1
+#define NR_AUTOLOAD_MSRS 8
 #define VMCS02_POOL_SIZE 1
 
 struct vmcs {
@@ -622,6 +623,7 @@ static unsigned long *vmx_msr_bitmap_legacy;
 static unsigned long *vmx_msr_bitmap_longmode;
 
 static bool cpu_has_load_ia32_efer;
+static bool cpu_has_load_perf_global_ctrl;
 
 static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
 static DEFINE_SPINLOCK(vmx_vpid_lock);
@@ -1191,15 +1193,34 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
        vmcs_write32(EXCEPTION_BITMAP, eb);
 }
 
+static void clear_atomic_switch_msr_special(unsigned long entry,
+               unsigned long exit)
+{
+       vmcs_clear_bits(VM_ENTRY_CONTROLS, entry);
+       vmcs_clear_bits(VM_EXIT_CONTROLS, exit);
+}
+
 static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
 {
        unsigned i;
        struct msr_autoload *m = &vmx->msr_autoload;
 
-       if (msr == MSR_EFER && cpu_has_load_ia32_efer) {
-               vmcs_clear_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER);
-               vmcs_clear_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER);
-               return;
+       switch (msr) {
+       case MSR_EFER:
+               if (cpu_has_load_ia32_efer) {
+                       clear_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER,
+                                       VM_EXIT_LOAD_IA32_EFER);
+                       return;
+               }
+               break;
+       case MSR_CORE_PERF_GLOBAL_CTRL:
+               if (cpu_has_load_perf_global_ctrl) {
+                       clear_atomic_switch_msr_special(
+                                       VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+                                       VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+                       return;
+               }
+               break;
        }
 
        for (i = 0; i < m->nr; ++i)
@@ -1215,25 +1236,55 @@ static void clear_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr)
        vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
 }
 
+static void add_atomic_switch_msr_special(unsigned long entry,
+               unsigned long exit, unsigned long guest_val_vmcs,
+               unsigned long host_val_vmcs, u64 guest_val, u64 host_val)
+{
+       vmcs_write64(guest_val_vmcs, guest_val);
+       vmcs_write64(host_val_vmcs, host_val);
+       vmcs_set_bits(VM_ENTRY_CONTROLS, entry);
+       vmcs_set_bits(VM_EXIT_CONTROLS, exit);
+}
+
 static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
                                  u64 guest_val, u64 host_val)
 {
        unsigned i;
        struct msr_autoload *m = &vmx->msr_autoload;
 
-       if (msr == MSR_EFER && cpu_has_load_ia32_efer) {
-               vmcs_write64(GUEST_IA32_EFER, guest_val);
-               vmcs_write64(HOST_IA32_EFER, host_val);
-               vmcs_set_bits(VM_ENTRY_CONTROLS, VM_ENTRY_LOAD_IA32_EFER);
-               vmcs_set_bits(VM_EXIT_CONTROLS, VM_EXIT_LOAD_IA32_EFER);
-               return;
+       switch (msr) {
+       case MSR_EFER:
+               if (cpu_has_load_ia32_efer) {
+                       add_atomic_switch_msr_special(VM_ENTRY_LOAD_IA32_EFER,
+                                       VM_EXIT_LOAD_IA32_EFER,
+                                       GUEST_IA32_EFER,
+                                       HOST_IA32_EFER,
+                                       guest_val, host_val);
+                       return;
+               }
+               break;
+       case MSR_CORE_PERF_GLOBAL_CTRL:
+               if (cpu_has_load_perf_global_ctrl) {
+                       add_atomic_switch_msr_special(
+                                       VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL,
+                                       VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL,
+                                       GUEST_IA32_PERF_GLOBAL_CTRL,
+                                       HOST_IA32_PERF_GLOBAL_CTRL,
+                                       guest_val, host_val);
+                       return;
+               }
+               break;
        }
 
        for (i = 0; i < m->nr; ++i)
                if (m->guest[i].index == msr)
                        break;
 
-       if (i == m->nr) {
+       if (i == NR_AUTOLOAD_MSRS) {
+               printk_once(KERN_WARNING"Not enough mst switch entries. "
+                               "Can't add msr %x\n", msr);
+               return;
+       } else if (i == m->nr) {
                ++m->nr;
                vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, m->nr);
                vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, m->nr);
@@ -2455,6 +2506,42 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf)
                && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
                                   VM_EXIT_LOAD_IA32_EFER);
 
+       cpu_has_load_perf_global_ctrl =
+               allow_1_setting(MSR_IA32_VMX_ENTRY_CTLS,
+                               VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL)
+               && allow_1_setting(MSR_IA32_VMX_EXIT_CTLS,
+                                  VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL);
+
+       /*
+        * Some cpus support VM_ENTRY_(LOAD|SAVE)_IA32_PERF_GLOBAL_CTRL
+        * but due to arrata below it can't be used. Workaround is to use
+        * msr load mechanism to switch IA32_PERF_GLOBAL_CTRL.
+        *
+        * VM Exit May Incorrectly Clear IA32_PERF_GLOBAL_CTRL [34:32]
+        *
+        * AAK155             (model 26)
+        * AAP115             (model 30)
+        * AAT100             (model 37)
+        * BC86,AAY89,BD102   (model 44)
+        * BA97               (model 46)
+        *
+        */
+       if (cpu_has_load_perf_global_ctrl && boot_cpu_data.x86 == 0x6) {
+               switch (boot_cpu_data.x86_model) {
+               case 26:
+               case 30:
+               case 37:
+               case 44:
+               case 46:
+                       cpu_has_load_perf_global_ctrl = false;
+                       printk_once(KERN_WARNING"kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
+                                       "does not work properly. Using workaround\n");
+                       break;
+               default:
+                       break;
+               }
+       }
+
        return 0;
 }
 
@@ -5968,6 +6055,24 @@ static void vmx_cancel_injection(struct kvm_vcpu *vcpu)
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);
 }
 
+static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
+{
+       int i, nr_msrs;
+       struct perf_guest_switch_msr *msrs;
+
+       msrs = perf_guest_get_msrs(&nr_msrs);
+
+       if (!msrs)
+               return;
+
+       for (i = 0; i < nr_msrs; i++)
+               if (msrs[i].host == msrs[i].guest)
+                       clear_atomic_switch_msr(vmx, msrs[i].msr);
+               else
+                       add_atomic_switch_msr(vmx, msrs[i].msr, msrs[i].guest,
+                                       msrs[i].host);
+}
+
 #ifdef CONFIG_X86_64
 #define R "r"
 #define Q "q"
@@ -6017,6 +6122,8 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
        if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
                vmx_set_interrupt_shadow(vcpu, 0);
 
+       atomic_switch_perf_msrs(vmx);
+
        vmx->__launched = vmx->loaded_vmcs->launched;
        asm(
                /* Store host registers */
index 28071bb..4c61b52 100644 (file)
@@ -109,7 +109,7 @@ static __init void sdv_serial_fixup(void)
 }
 
 #else
-static inline void sdv_serial_fixup(void);
+static inline void sdv_serial_fixup(void) {};
 #endif
 
 static void __init sdv_arch_setup(void)
index 6ed7afd..b1489a0 100644 (file)
@@ -187,11 +187,34 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
 static unsigned long __init mrst_calibrate_tsc(void)
 {
        unsigned long flags, fast_calibrate;
-
-       local_irq_save(flags);
-       fast_calibrate = apbt_quick_calibrate();
-       local_irq_restore(flags);
-
+       if (__mrst_cpu_chip == MRST_CPU_CHIP_PENWELL) {
+               u32 lo, hi, ratio, fsb;
+
+               rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
+               pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
+               ratio = (hi >> 8) & 0x1f;
+               pr_debug("ratio is %d\n", ratio);
+               if (!ratio) {
+                       pr_err("read a zero ratio, should be incorrect!\n");
+                       pr_err("force tsc ratio to 16 ...\n");
+                       ratio = 16;
+               }
+               rdmsr(MSR_FSB_FREQ, lo, hi);
+               if ((lo & 0x7) == 0x7)
+                       fsb = PENWELL_FSB_FREQ_83SKU;
+               else
+                       fsb = PENWELL_FSB_FREQ_100SKU;
+               fast_calibrate = ratio * fsb;
+               pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
+               lapic_timer_frequency = fsb * 1000 / HZ;
+               /* mark tsc clocksource as reliable */
+               set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
+       } else {
+               local_irq_save(flags);
+               fast_calibrate = apbt_quick_calibrate();
+               local_irq_restore(flags);
+       }
+       
        if (fast_calibrate)
                return fast_calibrate;
 
@@ -253,6 +276,17 @@ static void mrst_reboot(void)
        intel_scu_ipc_simple_command(0xf1, 0);
 }
 
+/*
+ * Moorestown does not have external NMI source nor port 0x61 to report
+ * NMI status. The possible NMI sources are from pmu as a result of NMI
+ * watchdog or lock debug. Reading io port 0x61 results in 0xff which
+ * misled NMI handler.
+ */
+static unsigned char mrst_get_nmi_reason(void)
+{
+       return 0;
+}
+
 /*
  * Moorestown specific x86_init function overrides and early setup
  * calls.
@@ -274,6 +308,8 @@ void __init x86_mrst_early_setup(void)
        x86_platform.calibrate_tsc = mrst_calibrate_tsc;
        x86_platform.i8042_detect = mrst_i8042_detect;
        x86_init.timers.wallclock_init = mrst_rtc_init;
+       x86_platform.get_nmi_reason = mrst_get_nmi_reason;
+
        x86_init.pci.init = pci_mrst_init;
        x86_init.pci.fixup_irqs = x86_init_noop;
 
@@ -608,6 +644,7 @@ static void *msic_ocd_platform_data(void *info)
 }
 
 static const struct devs_id __initconst device_ids[] = {
+       {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
        {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
        {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
        {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
index a8ac6f1..225bd0f 100644 (file)
@@ -76,8 +76,8 @@ unsigned long vrtc_get_time(void)
 
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       /* vRTC YEAR reg contains the offset to 1960 */
-       year += 1960;
+       /* vRTC YEAR reg contains the offset to 1972 */
+       year += 1972;
 
        printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d "
                "mon: %d year: %d\n", sec, min, hour, mday, mon, year);
index 118c143..2c32df6 100644 (file)
@@ -11,7 +11,7 @@
 #endif
 
 #define KSTK_EIP(tsk) KSTK_REG(tsk, HOST_IP)
-#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_IP)
+#define KSTK_ESP(tsk) KSTK_REG(tsk, HOST_SP)
 #define KSTK_EBP(tsk) KSTK_REG(tsk, HOST_BP)
 
 #define ARCH_IS_STACKGROW(address) \
index da8afd5..1f92865 100644 (file)
@@ -1356,7 +1356,7 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self,
        int cpu = (long)hcpu;
        switch (action) {
        case CPU_UP_PREPARE:
-               per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+               xen_vcpu_setup(cpu);
                if (xen_have_vector_callback)
                        xen_init_lock_cpu(cpu);
                break;
@@ -1386,7 +1386,6 @@ static void __init xen_hvm_guest_init(void)
        xen_hvm_smp_init();
        register_cpu_notifier(&xen_hvm_cpu_notifier);
        xen_unplug_emulated_devices();
-       have_vcpu_info_placement = 0;
        x86_init.irqs.intr_init = xen_init_IRQ;
        xen_hvm_init_time_ops();
        xen_hvm_init_mmu_ops();
index 6bbfd7a..5a40d24 100644 (file)
@@ -71,7 +71,7 @@ int arch_gnttab_map_shared(unsigned long *frames, unsigned long nr_gframes,
 
        if (shared == NULL) {
                struct vm_struct *area =
-                       alloc_vm_area(PAGE_SIZE * max_nr_gframes);
+                       alloc_vm_area(PAGE_SIZE * max_nr_gframes, NULL);
                BUG_ON(area == NULL);
                shared = area->addr;
                *__shared = shared;
index f43c8a5..ea70e6c 100644 (file)
@@ -1379,15 +1379,19 @@ get_rq:
                 */
                if (list_empty(&plug->list))
                        trace_block_plug(q);
-               else if (!plug->should_sort) {
-                       struct request *__rq;
+               else {
+                       if (!plug->should_sort) {
+                               struct request *__rq;
 
-                       __rq = list_entry_rq(plug->list.prev);
-                       if (__rq->q != q)
-                               plug->should_sort = 1;
+                               __rq = list_entry_rq(plug->list.prev);
+                               if (__rq->q != q)
+                                       plug->should_sort = 1;
+                       }
+                       if (request_count >= BLK_MAX_REQUEST_COUNT) {
+                               blk_flush_plug_list(plug, false);
+                               trace_block_plug(q);
+                       }
                }
-               if (request_count >= BLK_MAX_REQUEST_COUNT)
-                       blk_flush_plug_list(plug, false);
                list_add_tail(&req->queuelist, &plug->list);
                drive_stat_acct(req, 1);
        } else {
index e663ac2..164cd00 100644 (file)
@@ -204,10 +204,11 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
                if (!iov[i].iov_len)
                        return -EINVAL;
 
-               if (uaddr & queue_dma_alignment(q)) {
+               /*
+                * Keep going so we check length of all segments
+                */
+               if (uaddr & queue_dma_alignment(q))
                        unaligned = 1;
-                       break;
-               }
        }
 
        if (unaligned || (q->dma_pad_mask & len) || map_data)
index 9253839..02e9fca 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mutex.h>
 #include <linux/idr.h>
 #include <linux/log2.h>
-#include <linux/ctype.h>
 
 #include "blk.h"
 
@@ -916,74 +915,6 @@ static int __init genhd_device_init(void)
 
 subsys_initcall(genhd_device_init);
 
-static ssize_t alias_show(struct device *dev,
-                              struct device_attribute *attr, char *buf)
-{
-       struct gendisk *disk = dev_to_disk(dev);
-       ssize_t ret = 0;
-
-       if (disk->alias)
-               ret = snprintf(buf, ALIAS_LEN, "%s\n", disk->alias);
-       return ret;
-}
-
-static ssize_t alias_store(struct device *dev, struct device_attribute *attr,
-                          const char *buf, size_t count)
-{
-       struct gendisk *disk = dev_to_disk(dev);
-       char *alias;
-       char *envp[] = { NULL, NULL };
-       unsigned char c;
-       int i;
-       ssize_t ret = count;
-
-       if (!count)
-               return -EINVAL;
-
-       if (count >= ALIAS_LEN) {
-               printk(KERN_ERR "alias: alias is too long\n");
-               return -EINVAL;
-       }
-
-       /* Validation check */
-       for (i = 0; i < count; i++) {
-               c = buf[i];
-               if (i == count - 1 && c == '\n')
-                       break;
-               if (!isalnum(c) && c != '_' && c != '-') {
-                       printk(KERN_ERR "alias: invalid alias\n");
-                       return -EINVAL;
-               }
-       }
-
-       if (disk->alias) {
-               printk(KERN_INFO "alias: %s is already assigned (%s)\n",
-                      disk->disk_name, disk->alias);
-               return -EINVAL;
-       }
-
-       alias = kasprintf(GFP_KERNEL, "%s", buf);
-       if (!alias)
-               return -ENOMEM;
-
-       if (alias[count - 1] == '\n')
-               alias[count - 1] = '\0';
-
-       envp[0] = kasprintf(GFP_KERNEL, "ALIAS=%s", alias);
-       if (!envp[0]) {
-               kfree(alias);
-               return -ENOMEM;
-       }
-
-       disk->alias = alias;
-       printk(KERN_INFO "alias: assigned %s to %s\n", alias, disk->disk_name);
-
-       kobject_uevent_env(&dev->kobj, KOBJ_ADD, envp);
-
-       kfree(envp[0]);
-       return ret;
-}
-
 static ssize_t disk_range_show(struct device *dev,
                               struct device_attribute *attr, char *buf)
 {
@@ -1043,7 +974,6 @@ static ssize_t disk_discard_alignment_show(struct device *dev,
        return sprintf(buf, "%d\n", queue_discard_alignment(disk->queue));
 }
 
-static DEVICE_ATTR(alias, S_IRUGO|S_IWUSR, alias_show, alias_store);
 static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL);
 static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL);
 static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL);
@@ -1066,7 +996,6 @@ static struct device_attribute dev_attr_fail_timeout =
 #endif
 
 static struct attribute *disk_attrs[] = {
-       &dev_attr_alias.attr,
        &dev_attr_range.attr,
        &dev_attr_ext_range.attr,
        &dev_attr_removable.attr,
index a816f24..a0f768c 100644 (file)
@@ -383,6 +383,7 @@ static int crypto_init_ablkcipher_ops(struct crypto_tfm *tfm, u32 type,
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_blkcipher rblkcipher;
@@ -404,6 +405,12 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_ablkcipher_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
@@ -457,6 +464,7 @@ static int crypto_init_givcipher_ops(struct crypto_tfm *tfm, u32 type,
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_blkcipher rblkcipher;
@@ -478,6 +486,12 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_givcipher_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index 701556f..04add3d 100644 (file)
@@ -111,6 +111,7 @@ static int crypto_init_aead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_aead raead;
@@ -132,6 +133,12 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
@@ -190,6 +197,7 @@ static int crypto_init_nivaead_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_aead raead;
@@ -210,6 +218,12 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 
 static void crypto_nivaead_show(struct seq_file *m, struct crypto_alg *alg)
index a3e6ef9..ac93c99 100644 (file)
@@ -399,6 +399,7 @@ static unsigned int crypto_ahash_extsize(struct crypto_alg *alg)
        return sizeof(struct crypto_shash *);
 }
 
+#ifdef CONFIG_NET
 static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_hash rhash;
@@ -416,6 +417,12 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_ahash_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index 2572d26..1e61d1a 100644 (file)
@@ -494,6 +494,7 @@ static int crypto_init_blkcipher_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
                return crypto_init_blkcipher_ops_async(tfm);
 }
 
+#ifdef CONFIG_NET
 static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_blkcipher rblkcipher;
@@ -515,6 +516,12 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_blkcipher_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index 2abca78..0605a2b 100644 (file)
@@ -44,9 +44,6 @@ static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact)
 
        down_read(&crypto_alg_sem);
 
-       if (list_empty(&crypto_alg_list))
-               return NULL;
-
        list_for_each_entry(q, &crypto_alg_list, cra_list) {
                int match = 0;
 
index fefda78..2e458e5 100644 (file)
@@ -48,6 +48,7 @@ static int crypto_pcomp_init_tfm(struct crypto_tfm *tfm)
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_comp rpcomp;
@@ -62,6 +63,12 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_pcomp_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index feb7de0..64f864f 100644 (file)
@@ -60,6 +60,7 @@ static int crypto_init_rng_ops(struct crypto_tfm *tfm, u32 type, u32 mask)
        return 0;
 }
 
+#ifdef CONFIG_NET
 static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_rng rrng;
@@ -76,6 +77,12 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_rng_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index ea8a9c6..9100912 100644 (file)
@@ -524,6 +524,7 @@ static unsigned int crypto_shash_extsize(struct crypto_alg *alg)
        return alg->cra_ctxsize;
 }
 
+#ifdef CONFIG_NET
 static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
 {
        struct crypto_report_hash rhash;
@@ -541,6 +542,12 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
 nla_put_failure:
        return -EMSGSIZE;
 }
+#else
+static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg)
+{
+       return -ENOSYS;
+}
+#endif
 
 static void crypto_shash_show(struct seq_file *m, struct crypto_alg *alg)
        __attribute__ ((unused));
index 1274080..631b947 100644 (file)
@@ -932,7 +932,8 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
 static int erst_open_pstore(struct pstore_info *psi);
 static int erst_close_pstore(struct pstore_info *psi);
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-                          struct timespec *time, struct pstore_info *psi);
+                          struct timespec *time, char **buf,
+                          struct pstore_info *psi);
 static int erst_writer(enum pstore_type_id type, u64 *id, unsigned int part,
                       size_t size, struct pstore_info *psi);
 static int erst_clearer(enum pstore_type_id type, u64 id,
@@ -986,17 +987,23 @@ static int erst_close_pstore(struct pstore_info *psi)
 }
 
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-                          struct timespec *time, struct pstore_info *psi)
+                          struct timespec *time, char **buf,
+                          struct pstore_info *psi)
 {
        int rc;
        ssize_t len = 0;
        u64 record_id;
-       struct cper_pstore_record *rcd = (struct cper_pstore_record *)
-                                       (erst_info.buf - sizeof(*rcd));
+       struct cper_pstore_record *rcd;
+       size_t rcd_len = sizeof(*rcd) + erst_info.bufsize;
 
        if (erst_disable)
                return -ENODEV;
 
+       rcd = kmalloc(rcd_len, GFP_KERNEL);
+       if (!rcd) {
+               rc = -ENOMEM;
+               goto out;
+       }
 skip:
        rc = erst_get_record_id_next(&reader_pos, &record_id);
        if (rc)
@@ -1004,22 +1011,27 @@ skip:
 
        /* no more record */
        if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-               rc = -1;
+               rc = -EINVAL;
                goto out;
        }
 
-       len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
-                       erst_info.bufsize);
+       len = erst_read(record_id, &rcd->hdr, rcd_len);
        /* The record may be cleared by others, try read next record */
        if (len == -ENOENT)
                goto skip;
-       else if (len < 0) {
-               rc = -1;
+       else if (len < sizeof(*rcd)) {
+               rc = -EIO;
                goto out;
        }
        if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
                goto skip;
 
+       *buf = kmalloc(len, GFP_KERNEL);
+       if (*buf == NULL) {
+               rc = -ENOMEM;
+               goto out;
+       }
+       memcpy(*buf, rcd->data, len - sizeof(*rcd));
        *id = record_id;
        if (uuid_le_cmp(rcd->sec_hdr.section_type,
                        CPER_SECTION_TYPE_DMESG) == 0)
@@ -1037,6 +1049,7 @@ skip:
        time->tv_nsec = 0;
 
 out:
+       kfree(rcd);
        return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
index 73b2909..0e8e2de 100644 (file)
@@ -224,7 +224,6 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 /*
  * Suspend / resume control
  */
-static int acpi_idle_suspend;
 static u32 saved_bm_rld;
 
 static void acpi_idle_bm_rld_save(void)
@@ -243,21 +242,13 @@ static void acpi_idle_bm_rld_restore(void)
 
 int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
 {
-       if (acpi_idle_suspend == 1)
-               return 0;
-
        acpi_idle_bm_rld_save();
-       acpi_idle_suspend = 1;
        return 0;
 }
 
 int acpi_processor_resume(struct acpi_device * device)
 {
-       if (acpi_idle_suspend == 0)
-               return 0;
-
        acpi_idle_bm_rld_restore();
-       acpi_idle_suspend = 0;
        return 0;
 }
 
@@ -763,13 +754,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 
        local_irq_disable();
 
-       /* Do not access any ACPI IO ports in suspend path */
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return -EINVAL;
-       }
-
        lapic_timer_state_broadcast(pr, cx, 1);
        kt1 = ktime_get_real();
        acpi_idle_do_entry(cx);
@@ -810,13 +794,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 
        local_irq_disable();
 
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return -EINVAL;
-       }
-
-
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
                /*
@@ -895,12 +872,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
        if (unlikely(!pr))
                return -EINVAL;
 
-
-       if (acpi_idle_suspend) {
-               cpu_relax();
-               return -EINVAL;
-       }
-
        if (!cx->bm_sts_skip && acpi_idle_bm_check()) {
                if (drv->safe_state_index >= 0) {
                        return drv->states[drv->safe_state_index].enter(dev,
index fb7b90b..cf26222 100644 (file)
@@ -390,6 +390,9 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        /* Promise */
        { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },   /* PDC42819 */
 
+       /* Asmedia */
+       { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1061 */
+
        /* Generic, PCI class code for AHCI */
        { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
index 004f2ce..43b8758 100644 (file)
@@ -65,9 +65,9 @@ static struct scsi_host_template ahci_platform_sht = {
 static int __init ahci_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct ahci_platform_data *pdata = dev->platform_data;
+       struct ahci_platform_data *pdata = dev_get_platdata(dev);
        const struct platform_device_id *id = platform_get_device_id(pdev);
-       struct ata_port_info pi = ahci_port_info[id->driver_data];
+       struct ata_port_info pi = ahci_port_info[id ? id->driver_data : 0];
        const struct ata_port_info *ppi[] = { &pi, NULL };
        struct ahci_host_priv *hpriv;
        struct ata_host *host;
@@ -191,7 +191,7 @@ err0:
 static int __devexit ahci_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
-       struct ahci_platform_data *pdata = dev->platform_data;
+       struct ahci_platform_data *pdata = dev_get_platdata(dev);
        struct ata_host *host = dev_get_drvdata(dev);
 
        ata_host_detach(host);
index f22957c..a9b2820 100644 (file)
@@ -2883,7 +2883,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
            sata_scr_read(link, SCR_STATUS, &sstatus))
                rc = -ERESTART;
 
-       if (rc == -ERESTART || try >= max_tries) {
+       if (try >= max_tries) {
                /*
                 * Thaw host port even if reset failed, so that the port
                 * can be retried on the next phy event.  This risks
@@ -2909,6 +2909,16 @@ int ata_eh_reset(struct ata_link *link, int classify,
                ata_eh_acquire(ap);
        }
 
+       /*
+        * While disks spinup behind PMP, some controllers fail sending SRST.
+        * They need to be reset - as well as the PMP - before retrying.
+        */
+       if (rc == -ERESTART) {
+               if (ata_is_host_link(link))
+                       ata_eh_thaw_port(ap);
+               goto out;
+       }
+
        if (try == max_tries - 1) {
                sata_down_spd_limit(link, 0);
                if (slave)
index 104462d..21b80c5 100644 (file)
@@ -389,12 +389,9 @@ static void sata_pmp_quirks(struct ata_port *ap)
                        /* link reports offline after LPM */
                        link->flags |= ATA_LFLAG_NO_LPM;
 
-                       /* Class code report is unreliable and SRST
-                        * times out under certain configurations.
-                        */
+                       /* Class code report is unreliable. */
                        if (link->pmp < 5)
-                               link->flags |= ATA_LFLAG_NO_SRST |
-                                              ATA_LFLAG_ASSUME_ATA;
+                               link->flags |= ATA_LFLAG_ASSUME_ATA;
 
                        /* port 5 is for SEMB device and it doesn't like SRST */
                        if (link->pmp == 5)
index 72a9770..2a5412e 100644 (file)
@@ -1217,6 +1217,10 @@ void ata_scsi_slave_destroy(struct scsi_device *sdev)
 
 /**
  *     __ata_change_queue_depth - helper for ata_scsi_change_queue_depth
+ *     @ap: ATA port to which the device change the queue depth
+ *     @sdev: SCSI device to configure queue depth for
+ *     @queue_depth: new queue depth
+ *     @reason: calling context
  *
  *     libsas and libata have different approaches for associating a sdev to
  *     its ata_port.
index 63d5327..4cadfa2 100644 (file)
@@ -2533,10 +2533,12 @@ static int ata_pci_init_one(struct pci_dev *pdev,
        if (rc)
                goto out;
 
+#ifdef CONFIG_ATA_BMDMA
        if (bmdma)
                /* prepare and activate BMDMA host */
                rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host);
        else
+#endif
                /* prepare and activate SFF host */
                rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
        if (rc)
@@ -2544,10 +2546,12 @@ static int ata_pci_init_one(struct pci_dev *pdev,
        host->private_data = host_priv;
        host->flags |= hflags;
 
+#ifdef CONFIG_ATA_BMDMA
        if (bmdma) {
                pci_set_master(pdev);
                rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht);
        } else
+#endif
                rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
 out:
        if (rc == 0)
index a72ab0d..2a472c5 100644 (file)
@@ -52,7 +52,7 @@ static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
        }
 
        ret = of_irq_to_resource(dn, 0, &irq_res);
-       if (ret == NO_IRQ)
+       if (!ret)
                irq_res.start = irq_res.end = 0;
        else
                irq_res.flags = 0;
index 447d9c0..95ec435 100644 (file)
@@ -104,7 +104,7 @@ static const struct ata_port_info sis_port_info = {
 };
 
 MODULE_AUTHOR("Uwe Koziolek");
-MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
+MODULE_DESCRIPTION("low-level driver for Silicon Integrated Systems SATA controller");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, sis_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
index 82c8654..d8b3d89 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/kallsyms.h>
 #include <linux/mutex.h>
 #include <linux/async.h>
+#include <linux/pm_runtime.h>
 
 #include "base.h"
 #include "power/power.h"
@@ -1742,6 +1743,8 @@ void device_shutdown(void)
                 */
                list_del_init(&dev->kobj.entry);
                spin_unlock(&devices_kset->list_lock);
+               /* Disable all device's runtime power management */
+               pm_runtime_disable(dev);
 
                if (dev->bus && dev->bus->shutdown) {
                        dev_dbg(dev, "shutdown\n");
index 793f796..5693ece 100644 (file)
@@ -127,12 +127,13 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
                       nid, K(node_page_state(nid, NR_WRITEBACK)),
                       nid, K(node_page_state(nid, NR_FILE_PAGES)),
                       nid, K(node_page_state(nid, NR_FILE_MAPPED)),
-                      nid, K(node_page_state(nid, NR_ANON_PAGES)
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+                      nid, K(node_page_state(nid, NR_ANON_PAGES)
                        + node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-                       HPAGE_PMD_NR
+                       HPAGE_PMD_NR),
+#else
+                      nid, K(node_page_state(nid, NR_ANON_PAGES)),
 #endif
-                      ),
                       nid, K(node_page_state(nid, NR_SHMEM)),
                       nid, node_page_state(nid, NR_KERNEL_STACK) *
                                THREAD_SIZE / 1024,
@@ -143,13 +144,14 @@ static ssize_t node_read_meminfo(struct sys_device * dev,
                       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +
                                node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
                       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
-                      nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
+                      nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
                        , nid,
                        K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-                       HPAGE_PMD_NR)
+                       HPAGE_PMD_NR));
+#else
+                      nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));
 #endif
-                      );
        n += hugetlb_report_node_meminfo(nid, buf + n);
        return n;
 }
index 5f0f85d..428e55e 100644 (file)
@@ -229,7 +229,8 @@ int pm_clk_suspend(struct device *dev)
 
        list_for_each_entry_reverse(ce, &psd->clock_list, node) {
                if (ce->status < PCE_STATUS_ERROR) {
-                       clk_disable(ce->clk);
+                       if (ce->status == PCE_STATUS_ENABLED)
+                               clk_disable(ce->clk);
                        ce->status = PCE_STATUS_ACQUIRED;
                }
        }
index 7fa0984..c3d2dfc 100644 (file)
@@ -920,7 +920,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
  End:
        if (!error) {
                dev->power.is_suspended = true;
-               if (dev->power.wakeup_path && dev->parent)
+               if (dev->power.wakeup_path
+                   && dev->parent && !dev->parent->power.ignore_children)
                        dev->parent->power.wakeup_path = true;
        }
 
index 434a6c0..95706fa 100644 (file)
@@ -669,7 +669,7 @@ struct srcu_notifier_head *opp_get_notifier(struct device *dev)
        struct device_opp *dev_opp = find_device_opp(dev);
 
        if (IS_ERR(dev_opp))
-               return ERR_PTR(PTR_ERR(dev_opp)); /* matching type */
+               return ERR_CAST(dev_opp); /* matching type */
 
        return &dev_opp->head;
 }
index 30a94ea..86de6c5 100644 (file)
@@ -212,11 +212,9 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
        if (!dev || !req) /*guard against callers passing in null */
                return -EINVAL;
 
-       if (dev_pm_qos_request_active(req)) {
-               WARN(1, KERN_ERR "dev_pm_qos_add_request() called for already "
-                       "added request\n");
+       if (WARN(dev_pm_qos_request_active(req),
+                "%s() called for already added request\n", __func__))
                return -EINVAL;
-       }
 
        req->dev = dev;
 
@@ -271,11 +269,9 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
        if (!req) /*guard against callers passing in null */
                return -EINVAL;
 
-       if (!dev_pm_qos_request_active(req)) {
-               WARN(1, KERN_ERR "dev_pm_qos_update_request() called for "
-                       "unknown object\n");
+       if (WARN(!dev_pm_qos_request_active(req),
+                "%s() called for unknown object\n", __func__))
                return -EINVAL;
-       }
 
        mutex_lock(&dev_pm_qos_mtx);
 
@@ -312,11 +308,9 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
        if (!req) /*guard against callers passing in null */
                return -EINVAL;
 
-       if (!dev_pm_qos_request_active(req)) {
-               WARN(1, KERN_ERR "dev_pm_qos_remove_request() called for "
-                       "unknown object\n");
+       if (WARN(!dev_pm_qos_request_active(req),
+                "%s() called for unknown object\n", __func__))
                return -EINVAL;
-       }
 
        mutex_lock(&dev_pm_qos_mtx);
 
index 486f94e..8004ac3 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -4319,6 +4320,10 @@ static int __devinit cciss_pci_init(ctlr_info_t *h)
                dev_warn(&h->pdev->dev, "controller appears to be disabled\n");
                return -ENODEV;
        }
+
+       pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
+                               PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
+
        err = pci_enable_device(h->pdev);
        if (err) {
                dev_warn(&h->pdev->dev, "Unable to Enable PCI device\n");
@@ -5158,6 +5163,7 @@ reinit_after_soft_reset:
        h->cciss_max_sectors = 8192;
 
        rebuild_lun_table(h, 1, 0);
+       cciss_engage_scsi(h);
        h->busy_initializing = 0;
        return 1;
 
index 951a4e3..e820b68 100644 (file)
@@ -1720,5 +1720,6 @@ static int  cciss_eh_abort_handler(struct scsi_cmnd *scsicmd)
 /* If no tape support, then these become defined out of existence */
 
 #define cciss_scsi_setup(cntl_num)
+#define cciss_engage_scsi(h)
 
 #endif /* CONFIG_CISS_SCSI_TAPE */
index 3d80682..68b205a 100644 (file)
@@ -161,17 +161,19 @@ static struct loop_func_table *xfer_funcs[MAX_LO_CRYPT] = {
        &xor_funcs
 };
 
-static loff_t get_loop_size(struct loop_device *lo, struct file *file)
+static loff_t get_size(loff_t offset, loff_t sizelimit, struct file *file)
 {
-       loff_t size, offset, loopsize;
+       loff_t size, loopsize;
 
        /* Compute loopsize in bytes */
        size = i_size_read(file->f_mapping->host);
-       offset = lo->lo_offset;
        loopsize = size - offset;
-       if (lo->lo_sizelimit > 0 && lo->lo_sizelimit < loopsize)
-               loopsize = lo->lo_sizelimit;
+       /* offset is beyond i_size, wierd but possible */
+       if (loopsize < 0)
+               return 0;
 
+       if (sizelimit > 0 && sizelimit < loopsize)
+               loopsize = sizelimit;
        /*
         * Unfortunately, if we want to do I/O on the device,
         * the number of 512-byte sectors has to fit into a sector_t.
@@ -179,17 +181,25 @@ static loff_t get_loop_size(struct loop_device *lo, struct file *file)
        return loopsize >> 9;
 }
 
+static loff_t get_loop_size(struct loop_device *lo, struct file *file)
+{
+       return get_size(lo->lo_offset, lo->lo_sizelimit, file);
+}
+
 static int
-figure_loop_size(struct loop_device *lo)
+figure_loop_size(struct loop_device *lo, loff_t offset, loff_t sizelimit)
 {
-       loff_t size = get_loop_size(lo, lo->lo_backing_file);
+       loff_t size = get_size(offset, sizelimit, lo->lo_backing_file);
        sector_t x = (sector_t)size;
 
        if (unlikely((loff_t)x != size))
                return -EFBIG;
-
+       if (lo->lo_offset != offset)
+               lo->lo_offset = offset;
+       if (lo->lo_sizelimit != sizelimit)
+               lo->lo_sizelimit = sizelimit;
        set_capacity(lo->lo_disk, x);
-       return 0;                                       
+       return 0;
 }
 
 static inline int
@@ -372,7 +382,8 @@ do_lo_receive(struct loop_device *lo,
 
        if (retval < 0)
                return retval;
-
+       if (retval != bvec->bv_len)
+               return -EIO;
        return 0;
 }
 
@@ -1058,9 +1069,7 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 
        if (lo->lo_offset != info->lo_offset ||
            lo->lo_sizelimit != info->lo_sizelimit) {
-               lo->lo_offset = info->lo_offset;
-               lo->lo_sizelimit = info->lo_sizelimit;
-               if (figure_loop_size(lo))
+               if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit))
                        return -EFBIG;
        }
        loop_config_discard(lo);
@@ -1246,7 +1255,7 @@ static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev)
        err = -ENXIO;
        if (unlikely(lo->lo_state != Lo_bound))
                goto out;
-       err = figure_loop_size(lo);
+       err = figure_loop_size(lo, lo->lo_offset, lo->lo_sizelimit);
        if (unlikely(err))
                goto out;
        sec = get_capacity(lo->lo_disk);
@@ -1284,13 +1293,19 @@ static int lo_ioctl(struct block_device *bdev, fmode_t mode,
                        goto out_unlocked;
                break;
        case LOOP_SET_STATUS:
-               err = loop_set_status_old(lo, (struct loop_info __user *) arg);
+               err = -EPERM;
+               if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+                       err = loop_set_status_old(lo,
+                                       (struct loop_info __user *)arg);
                break;
        case LOOP_GET_STATUS:
                err = loop_get_status_old(lo, (struct loop_info __user *) arg);
                break;
        case LOOP_SET_STATUS64:
-               err = loop_set_status64(lo, (struct loop_info64 __user *) arg);
+               err = -EPERM;
+               if ((mode & FMODE_WRITE) || capable(CAP_SYS_ADMIN))
+                       err = loop_set_status64(lo,
+                                       (struct loop_info64 __user *) arg);
                break;
        case LOOP_GET_STATUS64:
                err = loop_get_status64(lo, (struct loop_info64 __user *) arg);
index 6b9a200..a79fb4f 100644 (file)
@@ -630,6 +630,7 @@ static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t
                if (dev->status & 0x10)
                        return -ETIME;
 
+       memset(&hdr, 0, sizeof(hdr));
        hdr.magic = PG_MAGIC;
        hdr.dlen = dev->dlen;
        copy = 0;
index f9b7260..fe4ebc3 100644 (file)
@@ -100,6 +100,9 @@ static struct usb_device_id btusb_table[] = {
        /* Canyon CN-BTU1 with HID interfaces */
        { USB_DEVICE(0x0c10, 0x0000) },
 
+       /* Broadcom BCM20702A0 */
+       { USB_DEVICE(0x413c, 0x8197) },
+
        { }     /* Terminating entry */
 };
 
index 66cd0b8..c92424c 100644 (file)
@@ -1186,10 +1186,11 @@ static void gen6_cleanup(void)
 /* Certain Gen5 chipsets require require idling the GPU before
  * unmapping anything from the GTT when VT-d is enabled.
  */
-extern int intel_iommu_gfx_mapped;
 static inline int needs_idle_maps(void)
 {
+#ifdef CONFIG_INTEL_IOMMU
        const unsigned short gpu_devid = intel_private.pcidev->device;
+       extern int intel_iommu_gfx_mapped;
 
        /* Query intel_iommu to see if we need the workaround. Presumably that
         * was loaded first.
@@ -1198,7 +1199,7 @@ static inline int needs_idle_maps(void)
             gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) &&
             intel_iommu_gfx_mapped)
                return 1;
-
+#endif
        return 0;
 }
 
@@ -1236,7 +1237,7 @@ static int i9xx_setup(void)
                intel_private.gtt_bus_addr = reg_addr + gtt_offset;
        }
 
-       if (needs_idle_maps());
+       if (needs_idle_maps())
                intel_private.base.do_idle_maps = 1;
 
        intel_i9xx_setup_flush();
index 63e19ba..6035ab8 100644 (file)
@@ -941,7 +941,7 @@ void get_random_bytes(void *buf, int nbytes)
                if (!arch_get_random_long(&v))
                        break;
                
-               memcpy(buf, &v, chunk);
+               memcpy(p, &v, chunk);
                p += chunk;
                nbytes -= chunk;
        }
index edaa987..f500201 100644 (file)
@@ -109,7 +109,7 @@ static unsigned int db8500_cpufreq_getspeed(unsigned int cpu)
 
 static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
 {
-       int res;
+       int i, res;
 
        BUILD_BUG_ON(ARRAY_SIZE(idx2opp) + 1 != ARRAY_SIZE(freq_table));
 
@@ -120,8 +120,8 @@ static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy)
                        freq_table[3].frequency = 1000000;
        }
        pr_info("db8500-cpufreq : Available frequencies:\n");
-       while (freq_table[i].frequency != CPUFREQ_TABLE_END)
-               pr_info("  %d Mhz\n", freq_table[i++].frequency/1000);
+       for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
+               pr_info("  %d Mhz\n", freq_table[i].frequency/1000);
 
        /* get policy fields based on the table */
        res = cpufreq_frequency_table_cpuinfo(policy, freq_table);
index 5c6f56f..dcd8bab 100644 (file)
@@ -343,11 +343,13 @@ static void mv_process_hash_current(int first_block)
                else
                        op.config |= CFG_MID_FRAG;
 
-               writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A);
-               writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B);
-               writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C);
-               writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D);
-               writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E);
+               if (first_block) {
+                       writel(req_ctx->state[0], cpg->reg + DIGEST_INITIAL_VAL_A);
+                       writel(req_ctx->state[1], cpg->reg + DIGEST_INITIAL_VAL_B);
+                       writel(req_ctx->state[2], cpg->reg + DIGEST_INITIAL_VAL_C);
+                       writel(req_ctx->state[3], cpg->reg + DIGEST_INITIAL_VAL_D);
+                       writel(req_ctx->state[4], cpg->reg + DIGEST_INITIAL_VAL_E);
+               }
        }
 
        memcpy(cpg->sram + SRAM_CONFIG, &op, sizeof(struct sec_accel_config));
index 643b055..8f04910 100644 (file)
@@ -1,36 +1,29 @@
-config ARCH_HAS_DEVFREQ
-       bool
-       depends on ARCH_HAS_OPP
-       help
-         Denotes that the architecture supports DEVFREQ. If the architecture
-         supports multiple OPP entries per device and the frequency of the
-         devices with OPPs may be altered dynamically, the architecture
-         supports DEVFREQ.
-
 menuconfig PM_DEVFREQ
        bool "Generic Dynamic Voltage and Frequency Scaling (DVFS) support"
-       depends on PM_OPP && ARCH_HAS_DEVFREQ
        help
-         With OPP support, a device may have a list of frequencies and
-         voltages available. DEVFREQ, a generic DVFS framework can be
-         registered for a device with OPP support in order to let the
-         governor provided to DEVFREQ choose an operating frequency
-         based on the OPP's list and the policy given with DEVFREQ.
+         A device may have a list of frequencies and voltages available.
+         devfreq, a generic DVFS framework can be registered for a device
+         in order to let the governor provided to devfreq choose an
+         operating frequency based on the device driver's policy.
 
-         Each device may have its own governor and policy. DEVFREQ can
+         Each device may have its own governor and policy. Devfreq can
          reevaluate the device state periodically and/or based on the
-         OPP list changes (each frequency/voltage pair in OPP may be
-         disabled or enabled).
+         notification to "nb", a notifier block, of devfreq.
 
-         Like some CPUs with CPUFREQ, a device may have multiple clocks.
+         Like some CPUs with CPUfreq, a device may have multiple clocks.
          However, because the clock frequencies of a single device are
-         determined by the single device's state, an instance of DEVFREQ
+         determined by the single device's state, an instance of devfreq
          is attached to a single device and returns a "representative"
-         clock frequency from the OPP of the device, which is also attached
-         to a device by 1-to-1. The device registering DEVFREQ takes the
-         responsiblity to "interpret" the frequency listed in OPP and
+         clock frequency of the device, which is also attached
+         to a device by 1-to-1. The device registering devfreq takes the
+         responsiblity to "interpret" the representative frequency and
          to set its every clock accordingly with the "target" callback
-         given to DEVFREQ.
+         given to devfreq.
+
+         When OPP is used with the devfreq device, it is recommended to
+         register devfreq's nb to the OPP's notifier head.  If OPP is
+         used with the devfreq device, you may use OPP helper
+         functions defined in devfreq.h.
 
 if PM_DEVFREQ
 
index 5d15b81..59d24e9 100644 (file)
@@ -15,7 +15,9 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/stat.h>
 #include <linux/opp.h>
 #include <linux/devfreq.h>
 #include <linux/workqueue.h>
@@ -416,10 +418,14 @@ out:
  */
 int devfreq_remove_device(struct devfreq *devfreq)
 {
+       bool central_polling;
+
        if (!devfreq)
                return -EINVAL;
 
-       if (!devfreq->governor->no_central_polling) {
+       central_polling = !devfreq->governor->no_central_polling;
+
+       if (central_polling) {
                mutex_lock(&devfreq_list_lock);
                while (wait_remove_device == devfreq) {
                        mutex_unlock(&devfreq_list_lock);
@@ -431,7 +437,7 @@ int devfreq_remove_device(struct devfreq *devfreq)
        mutex_lock(&devfreq->lock);
        _remove_devfreq(devfreq, false); /* it unlocks devfreq->lock */
 
-       if (!devfreq->governor->no_central_polling)
+       if (central_polling)
                mutex_unlock(&devfreq_list_lock);
 
        return 0;
index 8af8e86..73464a6 100644 (file)
@@ -1128,7 +1128,7 @@ static struct of_device_id mpc85xx_mc_err_of_match[] = {
        { .compatible = "fsl,p1020-memory-controller", },
        { .compatible = "fsl,p1021-memory-controller", },
        { .compatible = "fsl,p2020-memory-controller", },
-       { .compatible = "fsl,p4080-memory-controller", },
+       { .compatible = "fsl,qoriq-memory-controller", },
        {},
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
index bcb1126..153980b 100644 (file)
@@ -585,14 +585,12 @@ int dmi_name_in_serial(const char *str)
 }
 
 /**
- *     dmi_name_in_vendors - Check if string is anywhere in the DMI vendor information.
+ *     dmi_name_in_vendors - Check if string is in the DMI system or board vendor name
  *     @str:   Case sensitive Name
  */
 int dmi_name_in_vendors(const char *str)
 {
-       static int fields[] = { DMI_BIOS_VENDOR, DMI_BIOS_VERSION, DMI_SYS_VENDOR,
-                               DMI_PRODUCT_NAME, DMI_PRODUCT_VERSION, DMI_BOARD_VENDOR,
-                               DMI_BOARD_NAME, DMI_BOARD_VERSION, DMI_NONE };
+       static int fields[] = { DMI_SYS_VENDOR, DMI_BOARD_VENDOR, DMI_NONE };
        int i;
        for (i = 0; fields[i] != DMI_NONE; i++) {
                int f = fields[i];
index 8370f72..b0a8117 100644 (file)
@@ -457,7 +457,8 @@ static int efi_pstore_close(struct pstore_info *psi)
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-                              struct timespec *timespec, struct pstore_info *psi)
+                              struct timespec *timespec,
+                              char **buf, struct pstore_info *psi)
 {
        efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
        struct efivars *efivars = psi->data;
@@ -478,7 +479,11 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
                                timespec->tv_nsec = 0;
                                get_var_data_locked(efivars, &efivars->walk_entry->var);
                                size = efivars->walk_entry->var.DataSize;
-                               memcpy(psi->buf, efivars->walk_entry->var.Data, size);
+                               *buf = kmalloc(size, GFP_KERNEL);
+                               if (*buf == NULL)
+                                       return -ENOMEM;
+                               memcpy(*buf, efivars->walk_entry->var.Data,
+                                      size);
                                efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
                                                   struct efivar_entry, list);
                                return size;
@@ -576,7 +581,8 @@ static int efi_pstore_close(struct pstore_info *psi)
 }
 
 static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
-                              struct timespec *time, struct pstore_info *psi)
+                              struct timespec *timespec,
+                              char **buf, struct pstore_info *psi)
 {
        return -1;
 }
index 0e49d87..0b05629 100644 (file)
@@ -148,13 +148,17 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio)
        return (__raw_readl(reg) & GPIO_BIT(bank, gpio)) != 0;
 }
 
-#define MOD_REG_BIT(reg, bit_mask, set)        \
-do {   \
-       int l = __raw_readl(base + reg); \
-       if (set) l |= bit_mask; \
-       else l &= ~bit_mask; \
-       __raw_writel(l, base + reg); \
-} while(0)
+static inline void _gpio_rmw(void __iomem *base, u32 reg, u32 mask, bool set)
+{
+       int l = __raw_readl(base + reg);
+
+       if (set) 
+               l |= mask;
+       else
+               l &= ~mask;
+
+       __raw_writel(l, base + reg);
+}
 
 /**
  * _set_gpio_debounce - low level gpio debounce time
@@ -210,28 +214,28 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
        u32 gpio_bit = 1 << gpio;
 
        if (cpu_is_omap44xx()) {
-               MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT0, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_LOW);
-               MOD_REG_BIT(OMAP4_GPIO_LEVELDETECT1, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_HIGH);
-               MOD_REG_BIT(OMAP4_GPIO_RISINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_RISING);
-               MOD_REG_BIT(OMAP4_GPIO_FALLINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_FALLING);
+               _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT0, gpio_bit,
+                         trigger & IRQ_TYPE_LEVEL_LOW);
+               _gpio_rmw(base, OMAP4_GPIO_LEVELDETECT1, gpio_bit,
+                         trigger & IRQ_TYPE_LEVEL_HIGH);
+               _gpio_rmw(base, OMAP4_GPIO_RISINGDETECT, gpio_bit,
+                         trigger & IRQ_TYPE_EDGE_RISING);
+               _gpio_rmw(base, OMAP4_GPIO_FALLINGDETECT, gpio_bit,
+                         trigger & IRQ_TYPE_EDGE_FALLING);
        } else {
-               MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_LOW);
-               MOD_REG_BIT(OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
-                       trigger & IRQ_TYPE_LEVEL_HIGH);
-               MOD_REG_BIT(OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_RISING);
-               MOD_REG_BIT(OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
-                       trigger & IRQ_TYPE_EDGE_FALLING);
+               _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT0, gpio_bit,
+                         trigger & IRQ_TYPE_LEVEL_LOW);
+               _gpio_rmw(base, OMAP24XX_GPIO_LEVELDETECT1, gpio_bit,
+                         trigger & IRQ_TYPE_LEVEL_HIGH);
+               _gpio_rmw(base, OMAP24XX_GPIO_RISINGDETECT, gpio_bit,
+                         trigger & IRQ_TYPE_EDGE_RISING);
+               _gpio_rmw(base, OMAP24XX_GPIO_FALLINGDETECT, gpio_bit,
+                         trigger & IRQ_TYPE_EDGE_FALLING);
        }
        if (likely(!(bank->non_wakeup_gpios & gpio_bit))) {
                if (cpu_is_omap44xx()) {
-                       MOD_REG_BIT(OMAP4_GPIO_IRQWAKEN0, gpio_bit,
-                               trigger != 0);
+                       _gpio_rmw(base, OMAP4_GPIO_IRQWAKEN0, gpio_bit,
+                                 trigger != 0);
                } else {
                        /*
                         * GPIO wakeup request can only be generated on edge
@@ -1086,6 +1090,11 @@ omap_mpuio_alloc_gc(struct gpio_bank *bank, unsigned int irq_start,
 
        gc = irq_alloc_generic_chip("MPUIO", 1, irq_start, bank->base,
                                    handle_simple_irq);
+       if (!gc) {
+               dev_err(bank->dev, "Memory alloc failed for gc\n");
+               return;
+       }
+
        ct = gc->chip_types;
 
        /* NOTE: No ack required, reading IRQ status clears it. */
index 0550dcb..d3f3e8f 100644 (file)
@@ -546,7 +546,7 @@ static void pca953x_irq_teardown(struct pca953x_chip *chip)
  * Translate OpenFirmware node properties into platform_data
  * WARNING: This is DEPRECATED and will be removed eventually!
  */
-void
+static void
 pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
 {
        struct device_node *node;
@@ -574,7 +574,7 @@ pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
                *invert = *val;
 }
 #else
-void
+static void
 pca953x_get_alt_pdata(struct i2c_client *client, int *gpio_base, int *invert)
 {
        *gpio_base = -1;
@@ -596,9 +596,6 @@ static int __devinit device_pca953x_init(struct pca953x_chip *chip, int invert)
 
        /* set platform specific polarity inversion */
        ret = pca953x_write_reg(chip, PCA953X_INVERT, invert);
-       if (ret)
-               goto out;
-       return 0;
 out:
        return ret;
 }
@@ -640,7 +637,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
        struct pca953x_platform_data *pdata;
        struct pca953x_chip *chip;
        int irq_base=0, invert=0;
-       int ret = 0;
+       int ret;
 
        chip = kzalloc(sizeof(struct pca953x_chip), GFP_KERNEL);
        if (chip == NULL)
@@ -673,10 +670,10 @@ static int __devinit pca953x_probe(struct i2c_client *client,
        pca953x_setup_gpio(chip, id->driver_data & PCA_GPIO_MASK);
 
        if (chip->chip_type == PCA953X_TYPE)
-               device_pca953x_init(chip, invert);
-       else if (chip->chip_type == PCA957X_TYPE)
-               device_pca957x_init(chip, invert);
+               ret = device_pca953x_init(chip, invert);
        else
+               ret = device_pca957x_init(chip, invert);
+       if (ret)
                goto out_failed;
 
        ret = pca953x_irq_setup(chip, id, irq_base);
index 785127c..1368826 100644 (file)
@@ -9,7 +9,6 @@ menuconfig DRM
        depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
        select I2C
        select I2C_ALGOBIT
-       select SLOW_WORK
        help
          Kernel-level support for the Direct Rendering Infrastructure (DRI)
          introduced in XFree86 4.0. If you say Y here, you need to select
@@ -96,6 +95,7 @@ config DRM_I915
        select FB_CFB_IMAGEBLIT
        # i915 depends on ACPI_VIDEO when ACPI is enabled
        # but for select to work, need to select ACPI_VIDEO's dependencies, ick
+       select BACKLIGHT_LCD_SUPPORT if ACPI
        select BACKLIGHT_CLASS_DEVICE if ACPI
        select VIDEO_OUTPUT_CONTROL if ACPI
        select INPUT if ACPI
index 9a2e2a1..8323fc3 100644 (file)
@@ -1873,6 +1873,10 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
        }
 
        if (num_clips && clips_ptr) {
+               if (num_clips < 0 || num_clips > DRM_MODE_FB_DIRTY_MAX_CLIPS) {
+                       ret = -EINVAL;
+                       goto out_err1;
+               }
                clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL);
                if (!clips) {
                        ret = -ENOMEM;
@@ -2118,8 +2122,10 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
        property->num_values = num_values;
        INIT_LIST_HEAD(&property->enum_blob_list);
 
-       if (name)
+       if (name) {
                strncpy(property->name, name, DRM_PROP_NAME_LEN);
+               property->name[DRM_PROP_NAME_LEN-1] = '\0';
+       }
 
        list_add_tail(&property->head, &dev->mode_config.property_list);
        return property;
index 2957636..3969f75 100644 (file)
@@ -484,6 +484,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        struct drm_connector *save_connectors, *connector;
        int count = 0, ro, fail = 0;
        struct drm_crtc_helper_funcs *crtc_funcs;
+       struct drm_mode_set save_set;
        int ret = 0;
        int i;
 
@@ -556,6 +557,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                save_connectors[count++] = *connector;
        }
 
+       save_set.crtc = set->crtc;
+       save_set.mode = &set->crtc->mode;
+       save_set.x = set->crtc->x;
+       save_set.y = set->crtc->y;
+       save_set.fb = set->crtc->fb;
+
        /* We should be able to check here if the fb has the same properties
         * and then just flip_or_move it */
        if (set->crtc->fb != set->fb) {
@@ -721,6 +728,12 @@ fail:
                *connector = save_connectors[count++];
        }
 
+       /* Try to restore the config */
+       if (mode_changed &&
+           !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x,
+                                     save_set.y, save_set.fb))
+               DRM_ERROR("failed to restore config after modeset failure\n");
+
        kfree(save_connectors);
        kfree(save_encoders);
        kfree(save_crtcs);
index d067c12..1c7a1c0 100644 (file)
@@ -118,7 +118,10 @@ int drm_debugfs_create_files(struct drm_info_list *files, int count,
                tmp->minor = minor;
                tmp->dent = ent;
                tmp->info_ent = &files[i];
-               list_add(&(tmp->list), &(minor->debugfs_nodes.list));
+
+               mutex_lock(&minor->debugfs_lock);
+               list_add(&tmp->list, &minor->debugfs_list);
+               mutex_unlock(&minor->debugfs_lock);
        }
        return 0;
 
@@ -146,7 +149,8 @@ int drm_debugfs_init(struct drm_minor *minor, int minor_id,
        char name[64];
        int ret;
 
-       INIT_LIST_HEAD(&minor->debugfs_nodes.list);
+       INIT_LIST_HEAD(&minor->debugfs_list);
+       mutex_init(&minor->debugfs_lock);
        sprintf(name, "%d", minor_id);
        minor->debugfs_root = debugfs_create_dir(name, root);
        if (!minor->debugfs_root) {
@@ -192,8 +196,9 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count,
        struct drm_info_node *tmp;
        int i;
 
+       mutex_lock(&minor->debugfs_lock);
        for (i = 0; i < count; i++) {
-               list_for_each_safe(pos, q, &minor->debugfs_nodes.list) {
+               list_for_each_safe(pos, q, &minor->debugfs_list) {
                        tmp = list_entry(pos, struct drm_info_node, list);
                        if (tmp->info_ent == &files[i]) {
                                debugfs_remove(tmp->dent);
@@ -202,6 +207,7 @@ int drm_debugfs_remove_files(struct drm_info_list *files, int count,
                        }
                }
        }
+       mutex_unlock(&minor->debugfs_lock);
        return 0;
 }
 EXPORT_SYMBOL(drm_debugfs_remove_files);
index fc81af9..40c187c 100644 (file)
@@ -125,7 +125,7 @@ static struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
-       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0),
+       DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, DRM_UNLOCKED),
 
        DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_modeset_ctl, 0),
 
index cb3794a..44a5d0a 100644 (file)
@@ -110,10 +110,7 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
        /* Prevent vblank irq processing while disabling vblank irqs,
         * so no updates of timestamps or count can happen after we've
         * disabled. Needed to prevent races in case of delayed irq's.
-        * Disable preemption, so vblank_time_lock is held as short as
-        * possible, even under a kernel with PREEMPT_RT patches.
         */
-       preempt_disable();
        spin_lock_irqsave(&dev->vblank_time_lock, irqflags);
 
        dev->driver->disable_vblank(dev, crtc);
@@ -164,7 +161,6 @@ static void vblank_disable_and_save(struct drm_device *dev, int crtc)
        clear_vblank_timestamps(dev, crtc);
 
        spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
-       preempt_enable();
 }
 
 static void vblank_disable_fn(unsigned long arg)
@@ -407,13 +403,16 @@ int drm_irq_uninstall(struct drm_device *dev)
        /*
         * Wake up any waiters so they don't hang.
         */
-       spin_lock_irqsave(&dev->vbl_lock, irqflags);
-       for (i = 0; i < dev->num_crtcs; i++) {
-               DRM_WAKEUP(&dev->vbl_queue[i]);
-               dev->vblank_enabled[i] = 0;
-               dev->last_vblank[i] = dev->driver->get_vblank_counter(dev, i);
+       if (dev->num_crtcs) {
+               spin_lock_irqsave(&dev->vbl_lock, irqflags);
+               for (i = 0; i < dev->num_crtcs; i++) {
+                       DRM_WAKEUP(&dev->vbl_queue[i]);
+                       dev->vblank_enabled[i] = 0;
+                       dev->last_vblank[i] =
+                               dev->driver->get_vblank_counter(dev, i);
+               }
+               spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
        }
-       spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 
        if (!irq_enabled)
                return -EINVAL;
@@ -886,10 +885,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        /* Going from 0->1 means we have to enable interrupts again */
        if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1) {
-               /* Disable preemption while holding vblank_time_lock. Do
-                * it explicitely to guard against PREEMPT_RT kernel.
-                */
-               preempt_disable();
                spin_lock_irqsave(&dev->vblank_time_lock, irqflags2);
                if (!dev->vblank_enabled[crtc]) {
                        /* Enable vblank irqs under vblank_time_lock protection.
@@ -909,7 +904,6 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
                        }
                }
                spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags2);
-               preempt_enable();
        } else {
                if (!dev->vblank_enabled[crtc]) {
                        atomic_dec(&dev->vblank_refcount[crtc]);
@@ -1125,6 +1119,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
                trace_drm_vblank_event_delivered(current->pid, pipe,
                                                 vblwait->request.sequence);
        } else {
+               /* drm_handle_vblank_events will call drm_vblank_put */
                list_add_tail(&e->base.link, &dev->vblank_event_list);
                vblwait->reply.sequence = vblwait->request.sequence;
        }
@@ -1205,8 +1200,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
                goto done;
        }
 
-       if (flags & _DRM_VBLANK_EVENT)
+       if (flags & _DRM_VBLANK_EVENT) {
+               /* must hold on to the vblank ref until the event fires
+                * drm_vblank_put will be called asynchronously
+                */
                return drm_queue_vblank_event(dev, crtc, vblwait, file_priv);
+       }
 
        if ((flags & _DRM_VBLANK_NEXTONMISS) &&
            (seq - vblwait->request.sequence) <= (1<<23)) {
index 6f8afea..2bb07bc 100644 (file)
 #include "drm.h"
 
 #include "exynos_drm_drv.h"
+#include "exynos_drm_gem.h"
 #include "exynos_drm_buf.h"
 
-static DEFINE_MUTEX(exynos_drm_buf_lock);
-
 static int lowlevel_buffer_allocate(struct drm_device *dev,
-               struct exynos_drm_buf_entry *entry)
+               struct exynos_drm_gem_buf *buffer)
 {
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       entry->vaddr = dma_alloc_writecombine(dev->dev, entry->size,
-                       (dma_addr_t *)&entry->paddr, GFP_KERNEL);
-       if (!entry->paddr) {
+       buffer->kvaddr = dma_alloc_writecombine(dev->dev, buffer->size,
+                       &buffer->dma_addr, GFP_KERNEL);
+       if (!buffer->kvaddr) {
                DRM_ERROR("failed to allocate buffer.\n");
                return -ENOMEM;
        }
 
-       DRM_DEBUG_KMS("allocated : vaddr(0x%x), paddr(0x%x), size(0x%x)\n",
-                       (unsigned int)entry->vaddr, entry->paddr, entry->size);
+       DRM_DEBUG_KMS("vaddr(0x%lx), dma_addr(0x%lx), size(0x%lx)\n",
+                       (unsigned long)buffer->kvaddr,
+                       (unsigned long)buffer->dma_addr,
+                       buffer->size);
 
        return 0;
 }
 
 static void lowlevel_buffer_deallocate(struct drm_device *dev,
-               struct exynos_drm_buf_entry *entry)
+               struct exynos_drm_gem_buf *buffer)
 {
        DRM_DEBUG_KMS("%s.\n", __FILE__);
 
-       if (entry->paddr && entry->vaddr && entry->size)
-               dma_free_writecombine(dev->dev, entry->size, entry->vaddr,
-                               entry->paddr);
+       if (buffer->dma_addr && buffer->size)
+               dma_free_writecombine(dev->dev, buffer->size, buffer->kvaddr,
+                               (dma_addr_t)buffer->dma_addr);
        else
-               DRM_DEBUG_KMS("entry data is null.\n");
+               DRM_DEBUG_KMS("buffer data are invalid.\n");
 }
 
-struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
+struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
                unsigned int size)
 {
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
 
        DRM_DEBUG_KMS("%s.\n", __FILE__);
+       DRM_DEBUG_KMS("desired size = 0x%x\n", size);
 
-       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
-       if (!entry) {
-               DRM_ERROR("failed to allocate exynos_drm_buf_entry.\n");
+       buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
+       if (!buffer) {
+               DRM_ERROR("failed to allocate exynos_drm_gem_buf.\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       entry->size = size;
+       buffer->size = size;
 
        /*
         * allocate memory region with size and set the memory information
-        * to vaddr and paddr of a entry object.
+        * to vaddr and dma_addr of a buffer object.
         */
-       if (lowlevel_buffer_allocate(dev, entry) < 0) {
-               kfree(entry);
-               entry = NULL;
+       if (lowlevel_buffer_allocate(dev, buffer) < 0) {
+               kfree(buffer);
+               buffer = NULL;
                return ERR_PTR(-ENOMEM);
        }
 
-       return entry;
+       return buffer;
 }
 
 void exynos_drm_buf_destroy(struct drm_device *dev,
-               struct exynos_drm_buf_entry *entry)
+               struct exynos_drm_gem_buf *buffer)
 {
        DRM_DEBUG_KMS("%s.\n", __FILE__);
 
-       if (!entry) {
-               DRM_DEBUG_KMS("entry is null.\n");
+       if (!buffer) {
+               DRM_DEBUG_KMS("buffer is null.\n");
                return;
        }
 
-       lowlevel_buffer_deallocate(dev, entry);
+       lowlevel_buffer_deallocate(dev, buffer);
 
-       kfree(entry);
-       entry = NULL;
+       kfree(buffer);
+       buffer = NULL;
 }
 
 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
index 045d59e..6e91f9c 100644 (file)
 #ifndef _EXYNOS_DRM_BUF_H_
 #define _EXYNOS_DRM_BUF_H_
 
-/*
- * exynos drm buffer entry structure.
- *
- * @paddr: physical address of allocated memory.
- * @vaddr: kernel virtual address of allocated memory.
- * @size: size of allocated memory.
- */
-struct exynos_drm_buf_entry {
-       dma_addr_t paddr;
-       void __iomem *vaddr;
-       unsigned int size;
-};
-
 /* allocate physical memory. */
-struct exynos_drm_buf_entry *exynos_drm_buf_create(struct drm_device *dev,
+struct exynos_drm_gem_buf *exynos_drm_buf_create(struct drm_device *dev,
                unsigned int size);
 
-/* get physical memory information of a drm framebuffer. */
-struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
+/* get memory information of a drm framebuffer. */
+struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb);
 
 /* remove allocated physical memory. */
 void exynos_drm_buf_destroy(struct drm_device *dev,
-               struct exynos_drm_buf_entry *entry);
+               struct exynos_drm_gem_buf *buffer);
 
 #endif
index 985d9e7..d620b07 100644 (file)
@@ -37,6 +37,8 @@
 
 struct exynos_drm_connector {
        struct drm_connector    drm_connector;
+       uint32_t                encoder_id;
+       struct exynos_drm_manager *manager;
 };
 
 /* convert exynos_video_timings to drm_display_mode */
@@ -47,6 +49,7 @@ convert_to_display_mode(struct drm_display_mode *mode,
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        mode->clock = timing->pixclock / 1000;
+       mode->vrefresh = timing->refresh;
 
        mode->hdisplay = timing->xres;
        mode->hsync_start = mode->hdisplay + timing->left_margin;
@@ -57,6 +60,12 @@ convert_to_display_mode(struct drm_display_mode *mode,
        mode->vsync_start = mode->vdisplay + timing->upper_margin;
        mode->vsync_end = mode->vsync_start + timing->vsync_len;
        mode->vtotal = mode->vsync_end + timing->lower_margin;
+
+       if (timing->vmode & FB_VMODE_INTERLACED)
+               mode->flags |= DRM_MODE_FLAG_INTERLACE;
+
+       if (timing->vmode & FB_VMODE_DOUBLE)
+               mode->flags |= DRM_MODE_FLAG_DBLSCAN;
 }
 
 /* convert drm_display_mode to exynos_video_timings */
@@ -69,7 +78,7 @@ convert_to_video_timing(struct fb_videomode *timing,
        memset(timing, 0, sizeof(*timing));
 
        timing->pixclock = mode->clock * 1000;
-       timing->refresh = mode->vrefresh;
+       timing->refresh = drm_mode_vrefresh(mode);
 
        timing->xres = mode->hdisplay;
        timing->left_margin = mode->hsync_start - mode->hdisplay;
@@ -92,15 +101,16 @@ convert_to_video_timing(struct fb_videomode *timing,
 
 static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 {
-       struct exynos_drm_manager *manager =
-                               exynos_drm_get_manager(connector->encoder);
-       struct exynos_drm_display *display = manager->display;
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct exynos_drm_manager *manager = exynos_connector->manager;
+       struct exynos_drm_display_ops *display_ops = manager->display_ops;
        unsigned int count;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (!display) {
-               DRM_DEBUG_KMS("display is null.\n");
+       if (!display_ops) {
+               DRM_DEBUG_KMS("display_ops is null.\n");
                return 0;
        }
 
@@ -112,7 +122,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
         * P.S. in case of lcd panel, count is always 1 if success
         * because lcd panel has only one mode.
         */
-       if (display->get_edid) {
+       if (display_ops->get_edid) {
                int ret;
                void *edid;
 
@@ -122,7 +132,7 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
                        return 0;
                }
 
-               ret = display->get_edid(manager->dev, connector,
+               ret = display_ops->get_edid(manager->dev, connector,
                                                edid, MAX_EDID);
                if (ret < 0) {
                        DRM_ERROR("failed to get edid data.\n");
@@ -140,8 +150,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
                struct drm_display_mode *mode = drm_mode_create(connector->dev);
                struct fb_videomode *timing;
 
-               if (display->get_timing)
-                       timing = display->get_timing(manager->dev);
+               if (display_ops->get_timing)
+                       timing = display_ops->get_timing(manager->dev);
                else {
                        drm_mode_destroy(connector->dev, mode);
                        return 0;
@@ -162,9 +172,10 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector)
 static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
                                            struct drm_display_mode *mode)
 {
-       struct exynos_drm_manager *manager =
-                               exynos_drm_get_manager(connector->encoder);
-       struct exynos_drm_display *display = manager->display;
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct exynos_drm_manager *manager = exynos_connector->manager;
+       struct exynos_drm_display_ops *display_ops = manager->display_ops;
        struct fb_videomode timing;
        int ret = MODE_BAD;
 
@@ -172,8 +183,8 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
 
        convert_to_video_timing(&timing, mode);
 
-       if (display && display->check_timing)
-               if (!display->check_timing(manager->dev, (void *)&timing))
+       if (display_ops && display_ops->check_timing)
+               if (!display_ops->check_timing(manager->dev, (void *)&timing))
                        ret = MODE_OK;
 
        return ret;
@@ -181,9 +192,25 @@ static int exynos_drm_connector_mode_valid(struct drm_connector *connector,
 
 struct drm_encoder *exynos_drm_best_encoder(struct drm_connector *connector)
 {
+       struct drm_device *dev = connector->dev;
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct drm_mode_object *obj;
+       struct drm_encoder *encoder;
+
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       return connector->encoder;
+       obj = drm_mode_object_find(dev, exynos_connector->encoder_id,
+                                  DRM_MODE_OBJECT_ENCODER);
+       if (!obj) {
+               DRM_DEBUG_KMS("Unknown ENCODER ID %d\n",
+                               exynos_connector->encoder_id);
+               return NULL;
+       }
+
+       encoder = obj_to_encoder(obj);
+
+       return encoder;
 }
 
 static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
@@ -196,15 +223,17 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
 static enum drm_connector_status
 exynos_drm_connector_detect(struct drm_connector *connector, bool force)
 {
-       struct exynos_drm_manager *manager =
-                               exynos_drm_get_manager(connector->encoder);
-       struct exynos_drm_display *display = manager->display;
+       struct exynos_drm_connector *exynos_connector =
+                                       to_exynos_connector(connector);
+       struct exynos_drm_manager *manager = exynos_connector->manager;
+       struct exynos_drm_display_ops *display_ops =
+                                       manager->display_ops;
        enum drm_connector_status status = connector_status_disconnected;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       if (display && display->is_connected) {
-               if (display->is_connected(manager->dev))
+       if (display_ops && display_ops->is_connected) {
+               if (display_ops->is_connected(manager->dev))
                        status = connector_status_connected;
                else
                        status = connector_status_disconnected;
@@ -251,9 +280,11 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 
        connector = &exynos_connector->drm_connector;
 
-       switch (manager->display->type) {
+       switch (manager->display_ops->type) {
        case EXYNOS_DISPLAY_TYPE_HDMI:
                type = DRM_MODE_CONNECTOR_HDMIA;
+               connector->interlace_allowed = true;
+               connector->polled = DRM_CONNECTOR_POLL_HPD;
                break;
        default:
                type = DRM_MODE_CONNECTOR_Unknown;
@@ -267,7 +298,10 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
        if (err)
                goto err_connector;
 
+       exynos_connector->encoder_id = encoder->base.id;
+       exynos_connector->manager = manager;
        connector->encoder = encoder;
+
        err = drm_mode_connector_attach_encoder(connector, encoder);
        if (err) {
                DRM_ERROR("failed to attach a connector to a encoder\n");
index 9337e5e..ee43cc2 100644 (file)
 #include "drmP.h"
 #include "drm_crtc_helper.h"
 
+#include "exynos_drm_crtc.h"
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_encoder.h"
+#include "exynos_drm_gem.h"
 #include "exynos_drm_buf.h"
 
 #define to_exynos_crtc(x)      container_of(x, struct exynos_drm_crtc,\
                                drm_crtc)
 
-/*
- * Exynos specific crtc postion structure.
- *
- * @fb_x: offset x on a framebuffer to be displyed
- *     - the unit is screen coordinates.
- * @fb_y: offset y on a framebuffer to be displayed
- *     - the unit is screen coordinates.
- * @crtc_x: offset x on hardware screen.
- * @crtc_y: offset y on hardware screen.
- * @crtc_w: width of hardware screen.
- * @crtc_h: height of hardware screen.
- */
-struct exynos_drm_crtc_pos {
-       unsigned int fb_x;
-       unsigned int fb_y;
-       unsigned int crtc_x;
-       unsigned int crtc_y;
-       unsigned int crtc_w;
-       unsigned int crtc_h;
-};
-
 /*
  * Exynos specific crtc structure.
  *
@@ -85,30 +66,31 @@ static void exynos_drm_crtc_apply(struct drm_crtc *crtc)
 
        exynos_drm_fn_encoder(crtc, overlay,
                        exynos_drm_encoder_crtc_mode_set);
-       exynos_drm_fn_encoder(crtc, NULL, exynos_drm_encoder_crtc_commit);
+       exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                       exynos_drm_encoder_crtc_commit);
 }
 
-static int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
-                                      struct drm_framebuffer *fb,
-                                      struct drm_display_mode *mode,
-                                      struct exynos_drm_crtc_pos *pos)
+int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+                             struct drm_framebuffer *fb,
+                             struct drm_display_mode *mode,
+                             struct exynos_drm_crtc_pos *pos)
 {
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
        unsigned int actual_w;
        unsigned int actual_h;
 
-       entry = exynos_drm_fb_get_buf(fb);
-       if (!entry) {
-               DRM_LOG_KMS("entry is null.\n");
+       buffer = exynos_drm_fb_get_buf(fb);
+       if (!buffer) {
+               DRM_LOG_KMS("buffer is null.\n");
                return -EFAULT;
        }
 
-       overlay->paddr = entry->paddr;
-       overlay->vaddr = entry->vaddr;
+       overlay->dma_addr = buffer->dma_addr;
+       overlay->vaddr = buffer->kvaddr;
 
-       DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
+       DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
                        (unsigned long)overlay->vaddr,
-                       (unsigned long)overlay->paddr);
+                       (unsigned long)overlay->dma_addr);
 
        actual_w = min((mode->hdisplay - pos->crtc_x), pos->crtc_w);
        actual_h = min((mode->vdisplay - pos->crtc_y), pos->crtc_h);
@@ -171,9 +153,26 @@ static int exynos_drm_crtc_update(struct drm_crtc *crtc)
 
 static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
-       DRM_DEBUG_KMS("%s\n", __FILE__);
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
 
-       /* TODO */
+       DRM_DEBUG_KMS("crtc[%d] mode[%d]\n", crtc->base.id, mode);
+
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                               exynos_drm_encoder_crtc_commit);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               /* TODO */
+               exynos_drm_fn_encoder(crtc, NULL,
+                               exynos_drm_encoder_crtc_disable);
+               break;
+       default:
+               DRM_DEBUG_KMS("unspecified mode %d\n", mode);
+               break;
+       }
 }
 
 static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
@@ -185,9 +184,12 @@ static void exynos_drm_crtc_prepare(struct drm_crtc *crtc)
 
 static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
 {
+       struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc);
+
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       /* drm framework doesn't check NULL. */
+       exynos_drm_fn_encoder(crtc, &exynos_crtc->pipe,
+                       exynos_drm_encoder_crtc_commit);
 }
 
 static bool
index c584042..25f72a6 100644 (file)
@@ -35,4 +35,29 @@ int exynos_drm_crtc_create(struct drm_device *dev, unsigned int nr);
 int exynos_drm_crtc_enable_vblank(struct drm_device *dev, int crtc);
 void exynos_drm_crtc_disable_vblank(struct drm_device *dev, int crtc);
 
+/*
+ * Exynos specific crtc postion structure.
+ *
+ * @fb_x: offset x on a framebuffer to be displyed
+ *     - the unit is screen coordinates.
+ * @fb_y: offset y on a framebuffer to be displayed
+ *     - the unit is screen coordinates.
+ * @crtc_x: offset x on hardware screen.
+ * @crtc_y: offset y on hardware screen.
+ * @crtc_w: width of hardware screen.
+ * @crtc_h: height of hardware screen.
+ */
+struct exynos_drm_crtc_pos {
+       unsigned int fb_x;
+       unsigned int fb_y;
+       unsigned int crtc_x;
+       unsigned int crtc_y;
+       unsigned int crtc_w;
+       unsigned int crtc_h;
+};
+
+int exynos_drm_overlay_update(struct exynos_drm_overlay *overlay,
+                             struct drm_framebuffer *fb,
+                             struct drm_display_mode *mode,
+                             struct exynos_drm_crtc_pos *pos);
 #endif
index 83810cb..53e2216 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "drmP.h"
 #include "drm.h"
+#include "drm_crtc_helper.h"
 
 #include <drm/exynos_drm.h>
 
@@ -61,6 +62,9 @@ static int exynos_drm_load(struct drm_device *dev, unsigned long flags)
 
        drm_mode_config_init(dev);
 
+       /* init kms poll for handling hpd */
+       drm_kms_helper_poll_init(dev);
+
        exynos_drm_mode_config_init(dev);
 
        /*
@@ -116,6 +120,7 @@ static int exynos_drm_unload(struct drm_device *dev)
        exynos_drm_fbdev_fini(dev);
        exynos_drm_device_unregister(dev);
        drm_vblank_cleanup(dev);
+       drm_kms_helper_poll_fini(dev);
        drm_mode_config_cleanup(dev);
        kfree(dev->dev_private);
 
index c03683f..5e02e6e 100644 (file)
@@ -29,6 +29,7 @@
 #ifndef _EXYNOS_DRM_DRV_H_
 #define _EXYNOS_DRM_DRV_H_
 
+#include <linux/module.h>
 #include "drm.h"
 
 #define MAX_CRTC       2
@@ -79,8 +80,8 @@ struct exynos_drm_overlay_ops {
  * @scan_flag: interlace or progressive way.
  *     (it could be DRM_MODE_FLAG_*)
  * @bpp: pixel size.(in bit)
- * @paddr: bus(accessed by dma) physical memory address to this overlay
- *             and this is physically continuous.
+ * @dma_addr: bus(accessed by dma) address to the memory region allocated
+ *     for a overlay.
  * @vaddr: virtual memory addresss to this overlay.
  * @default_win: a window to be enabled.
  * @color_key: color key on or off.
@@ -108,7 +109,7 @@ struct exynos_drm_overlay {
        unsigned int scan_flag;
        unsigned int bpp;
        unsigned int pitch;
-       dma_addr_t paddr;
+       dma_addr_t dma_addr;
        void __iomem *vaddr;
 
        bool default_win;
@@ -130,7 +131,7 @@ struct exynos_drm_overlay {
  * @check_timing: check if timing is valid or not.
  * @power_on: display device on or off.
  */
-struct exynos_drm_display {
+struct exynos_drm_display_ops {
        enum exynos_drm_output_type type;
        bool (*is_connected)(struct device *dev);
        int (*get_edid)(struct device *dev, struct drm_connector *connector,
@@ -146,12 +147,14 @@ struct exynos_drm_display {
  * @mode_set: convert drm_display_mode to hw specific display mode and
  *           would be called by encoder->mode_set().
  * @commit: set current hw specific display mode to hw.
+ * @disable: disable hardware specific display mode.
  * @enable_vblank: specific driver callback for enabling vblank interrupt.
  * @disable_vblank: specific driver callback for disabling vblank interrupt.
  */
 struct exynos_drm_manager_ops {
        void (*mode_set)(struct device *subdrv_dev, void *mode);
        void (*commit)(struct device *subdrv_dev);
+       void (*disable)(struct device *subdrv_dev);
        int (*enable_vblank)(struct device *subdrv_dev);
        void (*disable_vblank)(struct device *subdrv_dev);
 };
@@ -178,7 +181,7 @@ struct exynos_drm_manager {
        int pipe;
        struct exynos_drm_manager_ops *ops;
        struct exynos_drm_overlay_ops *overlay_ops;
-       struct exynos_drm_display *display;
+       struct exynos_drm_display_ops *display_ops;
 };
 
 /*
index 7cf6fa8..1530614 100644 (file)
@@ -53,15 +53,36 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct drm_connector *connector;
        struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+       struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
        DRM_DEBUG_KMS("%s, encoder dpms: %d\n", __FILE__, mode);
 
+       switch (mode) {
+       case DRM_MODE_DPMS_ON:
+               if (manager_ops && manager_ops->commit)
+                       manager_ops->commit(manager->dev);
+               break;
+       case DRM_MODE_DPMS_STANDBY:
+       case DRM_MODE_DPMS_SUSPEND:
+       case DRM_MODE_DPMS_OFF:
+               /* TODO */
+               if (manager_ops && manager_ops->disable)
+                       manager_ops->disable(manager->dev);
+               break;
+       default:
+               DRM_ERROR("unspecified mode %d\n", mode);
+               break;
+       }
+
        list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
                if (connector->encoder == encoder) {
-                       struct exynos_drm_display *display = manager->display;
+                       struct exynos_drm_display_ops *display_ops =
+                                                       manager->display_ops;
 
-                       if (display && display->power_on)
-                               display->power_on(manager->dev, mode);
+                       DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
+                                       connector->base.id, mode);
+                       if (display_ops && display_ops->power_on)
+                               display_ops->power_on(manager->dev, mode);
                }
        }
 }
@@ -116,15 +137,11 @@ static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
        struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
        struct exynos_drm_manager_ops *manager_ops = manager->ops;
-       struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        if (manager_ops && manager_ops->commit)
                manager_ops->commit(manager->dev);
-
-       if (overlay_ops && overlay_ops->commit)
-               overlay_ops->commit(manager->dev);
 }
 
 static struct drm_crtc *
@@ -208,10 +225,23 @@ void exynos_drm_fn_encoder(struct drm_crtc *crtc, void *data,
 {
        struct drm_device *dev = crtc->dev;
        struct drm_encoder *encoder;
+       struct exynos_drm_private *private = dev->dev_private;
+       struct exynos_drm_manager *manager;
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-               if (encoder->crtc != crtc)
-                       continue;
+               /*
+                * if crtc is detached from encoder, check pipe,
+                * otherwise check crtc attached to encoder
+                */
+               if (!encoder->crtc) {
+                       manager = to_exynos_encoder(encoder)->manager;
+                       if (manager->pipe < 0 ||
+                                       private->crtc[manager->pipe] != crtc)
+                               continue;
+               } else {
+                       if (encoder->crtc != crtc)
+                               continue;
+               }
 
                fn(encoder, data);
        }
@@ -250,8 +280,18 @@ void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data)
        struct exynos_drm_manager *manager =
                to_exynos_encoder(encoder)->manager;
        struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+       int crtc = *(int *)data;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       /*
+        * when crtc is detached from encoder, this pipe is used
+        * to select manager operation
+        */
+       manager->pipe = crtc;
 
-       overlay_ops->commit(manager->dev);
+       if (overlay_ops && overlay_ops->commit)
+               overlay_ops->commit(manager->dev);
 }
 
 void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
@@ -261,7 +301,28 @@ void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data)
        struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
        struct exynos_drm_overlay *overlay = data;
 
-       overlay_ops->mode_set(manager->dev, overlay);
+       if (overlay_ops && overlay_ops->mode_set)
+               overlay_ops->mode_set(manager->dev, overlay);
+}
+
+void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data)
+{
+       struct exynos_drm_manager *manager =
+               to_exynos_encoder(encoder)->manager;
+       struct exynos_drm_overlay_ops *overlay_ops = manager->overlay_ops;
+
+       DRM_DEBUG_KMS("\n");
+
+       if (overlay_ops && overlay_ops->disable)
+               overlay_ops->disable(manager->dev);
+
+       /*
+        * crtc is already detached from encoder and last
+        * function for detaching is properly done, so
+        * clear pipe from manager to prevent repeated call
+        */
+       if (!encoder->crtc)
+               manager->pipe = -1;
 }
 
 MODULE_AUTHOR("Inki Dae <inki.dae@samsung.com>");
index 5ecd645..a22acfb 100644 (file)
@@ -41,5 +41,6 @@ void exynos_drm_enable_vblank(struct drm_encoder *encoder, void *data);
 void exynos_drm_disable_vblank(struct drm_encoder *encoder, void *data);
 void exynos_drm_encoder_crtc_commit(struct drm_encoder *encoder, void *data);
 void exynos_drm_encoder_crtc_mode_set(struct drm_encoder *encoder, void *data);
+void exynos_drm_encoder_crtc_disable(struct drm_encoder *encoder, void *data);
 
 #endif
index 48d29cf..5bf4a1a 100644 (file)
@@ -29,7 +29,9 @@
 #include "drmP.h"
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
+#include "drm_fb_helper.h"
 
+#include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
 #include "exynos_drm_buf.h"
 #include "exynos_drm_gem.h"
  *
  * @fb: drm framebuffer obejct.
  * @exynos_gem_obj: exynos specific gem object containing a gem object.
- * @entry: pointer to exynos drm buffer entry object.
- *     - containing only the information to physically continuous memory
- *     region allocated at default framebuffer creation.
+ * @buffer: pointer to exynos_drm_gem_buffer object.
+ *     - contain the memory information to memory region allocated
+ *     at default framebuffer creation.
  */
 struct exynos_drm_fb {
        struct drm_framebuffer          fb;
        struct exynos_drm_gem_obj       *exynos_gem_obj;
-       struct exynos_drm_buf_entry     *entry;
+       struct exynos_drm_gem_buf       *buffer;
 };
 
 static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
@@ -63,8 +65,8 @@ static void exynos_drm_fb_destroy(struct drm_framebuffer *fb)
         * default framebuffer has no gem object so
         * a buffer of the default framebuffer should be released at here.
         */
-       if (!exynos_fb->exynos_gem_obj && exynos_fb->entry)
-               exynos_drm_buf_destroy(fb->dev, exynos_fb->entry);
+       if (!exynos_fb->exynos_gem_obj && exynos_fb->buffer)
+               exynos_drm_buf_destroy(fb->dev, exynos_fb->buffer);
 
        kfree(exynos_fb);
        exynos_fb = NULL;
@@ -143,29 +145,29 @@ exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
         */
        if (!mode_cmd->handle) {
                if (!file_priv) {
-                       struct exynos_drm_buf_entry *entry;
+                       struct exynos_drm_gem_buf *buffer;
 
                        /*
                         * in case that file_priv is NULL, it allocates
                         * only buffer and this buffer would be used
                         * for default framebuffer.
                         */
-                       entry = exynos_drm_buf_create(dev, size);
-                       if (IS_ERR(entry)) {
-                               ret = PTR_ERR(entry);
+                       buffer = exynos_drm_buf_create(dev, size);
+                       if (IS_ERR(buffer)) {
+                               ret = PTR_ERR(buffer);
                                goto err_buffer;
                        }
 
-                       exynos_fb->entry = entry;
+                       exynos_fb->buffer = buffer;
 
-                       DRM_LOG_KMS("default fb: paddr = 0x%lx, size = 0x%x\n",
-                                       (unsigned long)entry->paddr, size);
+                       DRM_LOG_KMS("default: dma_addr = 0x%lx, size = 0x%x\n",
+                                       (unsigned long)buffer->dma_addr, size);
 
                        goto out;
                } else {
-                       exynos_gem_obj = exynos_drm_gem_create(file_priv, dev,
-                                                       size,
-                                                       &mode_cmd->handle);
+                       exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
+                                                       &mode_cmd->handle,
+                                                       size);
                        if (IS_ERR(exynos_gem_obj)) {
                                ret = PTR_ERR(exynos_gem_obj);
                                goto err_buffer;
@@ -189,10 +191,10 @@ exynos_drm_fb_init(struct drm_file *file_priv, struct drm_device *dev,
         * so that default framebuffer has no its own gem object,
         * only its own buffer object.
         */
-       exynos_fb->entry = exynos_gem_obj->entry;
+       exynos_fb->buffer = exynos_gem_obj->buffer;
 
-       DRM_LOG_KMS("paddr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
-                       (unsigned long)exynos_fb->entry->paddr, size,
+       DRM_LOG_KMS("dma_addr = 0x%lx, size = 0x%x, gem object = 0x%x\n",
+                       (unsigned long)exynos_fb->buffer->dma_addr, size,
                        (unsigned int)&exynos_gem_obj->base);
 
 out:
@@ -220,26 +222,36 @@ struct drm_framebuffer *exynos_drm_fb_create(struct drm_device *dev,
        return exynos_drm_fb_init(file_priv, dev, mode_cmd);
 }
 
-struct exynos_drm_buf_entry *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
+struct exynos_drm_gem_buf *exynos_drm_fb_get_buf(struct drm_framebuffer *fb)
 {
        struct exynos_drm_fb *exynos_fb = to_exynos_fb(fb);
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       entry = exynos_fb->entry;
-       if (!entry)
+       buffer = exynos_fb->buffer;
+       if (!buffer)
                return NULL;
 
-       DRM_DEBUG_KMS("vaddr = 0x%lx, paddr = 0x%lx\n",
-                       (unsigned long)entry->vaddr,
-                       (unsigned long)entry->paddr);
+       DRM_DEBUG_KMS("vaddr = 0x%lx, dma_addr = 0x%lx\n",
+                       (unsigned long)buffer->kvaddr,
+                       (unsigned long)buffer->dma_addr);
 
-       return entry;
+       return buffer;
+}
+
+static void exynos_drm_output_poll_changed(struct drm_device *dev)
+{
+       struct exynos_drm_private *private = dev->dev_private;
+       struct drm_fb_helper *fb_helper = private->fb_helper;
+
+       if (fb_helper)
+               drm_fb_helper_hotplug_event(fb_helper);
 }
 
 static struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {
        .fb_create = exynos_drm_fb_create,
+       .output_poll_changed = exynos_drm_output_poll_changed,
 };
 
 void exynos_drm_mode_config_init(struct drm_device *dev)
index 1f4b3d1..836f410 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_fb.h"
+#include "exynos_drm_gem.h"
 #include "exynos_drm_buf.h"
 
 #define MAX_CONNECTOR          4
@@ -85,15 +86,13 @@ static struct fb_ops exynos_drm_fb_ops = {
 };
 
 static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
-                                    struct drm_framebuffer *fb,
-                                    unsigned int fb_width,
-                                    unsigned int fb_height)
+                                    struct drm_framebuffer *fb)
 {
        struct fb_info *fbi = helper->fbdev;
        struct drm_device *dev = helper->dev;
        struct exynos_drm_fbdev *exynos_fb = to_exynos_fbdev(helper);
-       struct exynos_drm_buf_entry *entry;
-       unsigned int size = fb_width * fb_height * (fb->bits_per_pixel >> 3);
+       struct exynos_drm_gem_buf *buffer;
+       unsigned int size = fb->width * fb->height * (fb->bits_per_pixel >> 3);
        unsigned long offset;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -101,20 +100,20 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
        exynos_fb->fb = fb;
 
        drm_fb_helper_fill_fix(fbi, fb->pitch, fb->depth);
-       drm_fb_helper_fill_var(fbi, helper, fb_width, fb_height);
+       drm_fb_helper_fill_var(fbi, helper, fb->width, fb->height);
 
-       entry = exynos_drm_fb_get_buf(fb);
-       if (!entry) {
-               DRM_LOG_KMS("entry is null.\n");
+       buffer = exynos_drm_fb_get_buf(fb);
+       if (!buffer) {
+               DRM_LOG_KMS("buffer is null.\n");
                return -EFAULT;
        }
 
        offset = fbi->var.xoffset * (fb->bits_per_pixel >> 3);
        offset += fbi->var.yoffset * fb->pitch;
 
-       dev->mode_config.fb_base = entry->paddr;
-       fbi->screen_base = entry->vaddr + offset;
-       fbi->fix.smem_start = entry->paddr + offset;
+       dev->mode_config.fb_base = (resource_size_t)buffer->dma_addr;
+       fbi->screen_base = buffer->kvaddr + offset;
+       fbi->fix.smem_start = (unsigned long)(buffer->dma_addr + offset);
        fbi->screen_size = size;
        fbi->fix.smem_len = size;
 
@@ -171,8 +170,7 @@ static int exynos_drm_fbdev_create(struct drm_fb_helper *helper,
                goto out;
        }
 
-       ret = exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
-                       sizes->fb_height);
+       ret = exynos_drm_fbdev_update(helper, helper->fb);
        if (ret < 0)
                fb_dealloc_cmap(&fbi->cmap);
 
@@ -235,8 +233,7 @@ static int exynos_drm_fbdev_recreate(struct drm_fb_helper *helper,
        }
 
        helper->fb = exynos_fbdev->fb;
-       return exynos_drm_fbdev_update(helper, helper->fb, sizes->fb_width,
-                       sizes->fb_height);
+       return exynos_drm_fbdev_update(helper, helper->fb);
 }
 
 static int exynos_drm_fbdev_probe(struct drm_fb_helper *helper,
@@ -405,6 +402,18 @@ int exynos_drm_fbdev_reinit(struct drm_device *dev)
        fb_helper = private->fb_helper;
 
        if (fb_helper) {
+               struct list_head temp_list;
+
+               INIT_LIST_HEAD(&temp_list);
+
+               /*
+                * fb_helper is reintialized but kernel fb is reused
+                * so kernel_fb_list need to be backuped and restored
+                */
+               if (!list_empty(&fb_helper->kernel_fb_list))
+                       list_replace_init(&fb_helper->kernel_fb_list,
+                                       &temp_list);
+
                drm_fb_helper_fini(fb_helper);
 
                ret = drm_fb_helper_init(dev, fb_helper,
@@ -414,6 +423,9 @@ int exynos_drm_fbdev_reinit(struct drm_device *dev)
                        return ret;
                }
 
+               if (!list_empty(&temp_list))
+                       list_replace(&temp_list, &fb_helper->kernel_fb_list);
+
                ret = drm_fb_helper_single_add_all_connectors(fb_helper);
                if (ret < 0) {
                        DRM_ERROR("failed to add fb helper to connectors\n");
index 4659c88..db3b3d9 100644 (file)
@@ -64,7 +64,7 @@ struct fimd_win_data {
        unsigned int            fb_width;
        unsigned int            fb_height;
        unsigned int            bpp;
-       dma_addr_t              paddr;
+       dma_addr_t              dma_addr;
        void __iomem            *vaddr;
        unsigned int            buf_offsize;
        unsigned int            line_size;      /* bytes */
@@ -124,7 +124,7 @@ static int fimd_display_power_on(struct device *dev, int mode)
        return 0;
 }
 
-static struct exynos_drm_display fimd_display = {
+static struct exynos_drm_display_ops fimd_display_ops = {
        .type = EXYNOS_DISPLAY_TYPE_LCD,
        .is_connected = fimd_display_is_connected,
        .get_timing = fimd_get_timing,
@@ -177,6 +177,40 @@ static void fimd_commit(struct device *dev)
        writel(val, ctx->regs + VIDCON0);
 }
 
+static void fimd_disable(struct device *dev)
+{
+       struct fimd_context *ctx = get_fimd_context(dev);
+       struct exynos_drm_subdrv *subdrv = &ctx->subdrv;
+       struct drm_device *drm_dev = subdrv->drm_dev;
+       struct exynos_drm_manager *manager = &subdrv->manager;
+       u32 val;
+
+       DRM_DEBUG_KMS("%s\n", __FILE__);
+
+       /* fimd dma off */
+       val = readl(ctx->regs + VIDCON0);
+       val &= ~(VIDCON0_ENVID | VIDCON0_ENVID_F);
+       writel(val, ctx->regs + VIDCON0);
+
+       /*
+        * if vblank is enabled status with dma off then
+        * it disables vsync interrupt.
+        */
+       if (drm_dev->vblank_enabled[manager->pipe] &&
+               atomic_read(&drm_dev->vblank_refcount[manager->pipe])) {
+               drm_vblank_put(drm_dev, manager->pipe);
+
+               /*
+                * if vblank_disable_allowed is 0 then disable
+                * vsync interrupt right now else the vsync interrupt
+                * would be disabled by drm timer once a current process
+                * gives up ownershop of vblank event.
+                */
+               if (!drm_dev->vblank_disable_allowed)
+                       drm_vblank_off(drm_dev, manager->pipe);
+       }
+}
+
 static int fimd_enable_vblank(struct device *dev)
 {
        struct fimd_context *ctx = get_fimd_context(dev);
@@ -220,6 +254,7 @@ static void fimd_disable_vblank(struct device *dev)
 
 static struct exynos_drm_manager_ops fimd_manager_ops = {
        .commit = fimd_commit,
+       .disable = fimd_disable,
        .enable_vblank = fimd_enable_vblank,
        .disable_vblank = fimd_disable_vblank,
 };
@@ -251,7 +286,7 @@ static void fimd_win_mode_set(struct device *dev,
        win_data->ovl_height = overlay->crtc_height;
        win_data->fb_width = overlay->fb_width;
        win_data->fb_height = overlay->fb_height;
-       win_data->paddr = overlay->paddr + offset;
+       win_data->dma_addr = overlay->dma_addr + offset;
        win_data->vaddr = overlay->vaddr + offset;
        win_data->bpp = overlay->bpp;
        win_data->buf_offsize = (overlay->fb_width - overlay->crtc_width) *
@@ -263,7 +298,7 @@ static void fimd_win_mode_set(struct device *dev,
        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
                        win_data->ovl_width, win_data->ovl_height);
        DRM_DEBUG_KMS("paddr = 0x%lx, vaddr = 0x%lx\n",
-                       (unsigned long)win_data->paddr,
+                       (unsigned long)win_data->dma_addr,
                        (unsigned long)win_data->vaddr);
        DRM_DEBUG_KMS("fb_width = %d, crtc_width = %d\n",
                        overlay->fb_width, overlay->crtc_width);
@@ -376,16 +411,16 @@ static void fimd_win_commit(struct device *dev)
        writel(val, ctx->regs + SHADOWCON);
 
        /* buffer start address */
-       val = win_data->paddr;
+       val = (unsigned long)win_data->dma_addr;
        writel(val, ctx->regs + VIDWx_BUF_START(win, 0));
 
        /* buffer end address */
        size = win_data->fb_width * win_data->ovl_height * (win_data->bpp >> 3);
-       val = win_data->paddr + size;
+       val = (unsigned long)(win_data->dma_addr + size);
        writel(val, ctx->regs + VIDWx_BUF_END(win, 0));
 
        DRM_DEBUG_KMS("start addr = 0x%lx, end addr = 0x%lx, size = 0x%lx\n",
-                       (unsigned long)win_data->paddr, val, size);
+                       (unsigned long)win_data->dma_addr, val, size);
        DRM_DEBUG_KMS("ovl_width = %d, ovl_height = %d\n",
                        win_data->ovl_width, win_data->ovl_height);
 
@@ -447,7 +482,6 @@ static void fimd_win_commit(struct device *dev)
 static void fimd_win_disable(struct device *dev)
 {
        struct fimd_context *ctx = get_fimd_context(dev);
-       struct fimd_win_data *win_data;
        int win = ctx->default_win;
        u32 val;
 
@@ -456,8 +490,6 @@ static void fimd_win_disable(struct device *dev)
        if (win < 0 || win > WINDOWS_NR)
                return;
 
-       win_data = &ctx->win_data[win];
-
        /* protect windows */
        val = readl(ctx->regs + SHADOWCON);
        val |= SHADOWCON_WINx_PROTECT(win);
@@ -528,6 +560,16 @@ static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
                /* VSYNC interrupt */
                writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1);
 
+       /*
+        * in case that vblank_disable_allowed is 1, it could induce
+        * the problem that manager->pipe could be -1 because with
+        * disable callback, vsync interrupt isn't disabled and at this moment,
+        * vsync interrupt could occur. the vsync interrupt would be disabled
+        * by timer handler later.
+        */
+       if (manager->pipe == -1)
+               return IRQ_HANDLED;
+
        drm_handle_vblank(drm_dev, manager->pipe);
        fimd_finish_pageflip(drm_dev, manager->pipe);
 
@@ -548,13 +590,6 @@ static int fimd_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
         */
        drm_dev->irq_enabled = 1;
 
-       /*
-        * with vblank_disable_allowed = 1, vblank interrupt will be disabled
-        * by drm timer once a current process gives up ownership of
-        * vblank event.(drm_vblank_put function was called)
-        */
-       drm_dev->vblank_disable_allowed = 1;
-
        return 0;
 }
 
@@ -731,7 +766,7 @@ static int __devinit fimd_probe(struct platform_device *pdev)
        subdrv->manager.pipe = -1;
        subdrv->manager.ops = &fimd_manager_ops;
        subdrv->manager.overlay_ops = &fimd_overlay_ops;
-       subdrv->manager.display = &fimd_display;
+       subdrv->manager.display_ops = &fimd_display_ops;
        subdrv->manager.dev = dev;
 
        platform_set_drvdata(pdev, ctx);
index a8e7a88..aba0fe4 100644 (file)
@@ -62,40 +62,28 @@ static unsigned int get_gem_mmap_offset(struct drm_gem_object *obj)
        return (unsigned int)obj->map_list.hash.key << PAGE_SHIFT;
 }
 
-struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv,
-               struct drm_device *dev, unsigned int size,
-               unsigned int *handle)
+static struct exynos_drm_gem_obj
+               *exynos_drm_gem_init(struct drm_device *drm_dev,
+                       struct drm_file *file_priv, unsigned int *handle,
+                       unsigned int size)
 {
        struct exynos_drm_gem_obj *exynos_gem_obj;
-       struct exynos_drm_buf_entry *entry;
        struct drm_gem_object *obj;
        int ret;
 
-       DRM_DEBUG_KMS("%s\n", __FILE__);
-
-       size = roundup(size, PAGE_SIZE);
-
        exynos_gem_obj = kzalloc(sizeof(*exynos_gem_obj), GFP_KERNEL);
        if (!exynos_gem_obj) {
                DRM_ERROR("failed to allocate exynos gem object.\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       /* allocate the new buffer object and memory region. */
-       entry = exynos_drm_buf_create(dev, size);
-       if (!entry) {
-               kfree(exynos_gem_obj);
-               return ERR_PTR(-ENOMEM);
-       }
-
-       exynos_gem_obj->entry = entry;
-
        obj = &exynos_gem_obj->base;
 
-       ret = drm_gem_object_init(dev, obj, size);
+       ret = drm_gem_object_init(drm_dev, obj, size);
        if (ret < 0) {
-               DRM_ERROR("failed to initailize gem object.\n");
-               goto err_obj_init;
+               DRM_ERROR("failed to initialize gem object.\n");
+               ret = -EINVAL;
+               goto err_object_init;
        }
 
        DRM_DEBUG_KMS("created file object = 0x%x\n", (unsigned int)obj->filp);
@@ -127,24 +115,50 @@ err_handle_create:
 err_create_mmap_offset:
        drm_gem_object_release(obj);
 
-err_obj_init:
-       exynos_drm_buf_destroy(dev, exynos_gem_obj->entry);
-
+err_object_init:
        kfree(exynos_gem_obj);
 
        return ERR_PTR(ret);
 }
 
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
+                               struct drm_file *file_priv,
+                               unsigned int *handle, unsigned long size)
+{
+
+       struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
+       struct exynos_drm_gem_buf *buffer;
+
+       size = roundup(size, PAGE_SIZE);
+
+       DRM_DEBUG_KMS("%s: size = 0x%lx\n", __FILE__, size);
+
+       buffer = exynos_drm_buf_create(dev, size);
+       if (IS_ERR(buffer)) {
+               return ERR_CAST(buffer);
+       }
+
+       exynos_gem_obj = exynos_drm_gem_init(dev, file_priv, handle, size);
+       if (IS_ERR(exynos_gem_obj)) {
+               exynos_drm_buf_destroy(dev, buffer);
+               return exynos_gem_obj;
+       }
+
+       exynos_gem_obj->buffer = buffer;
+
+       return exynos_gem_obj;
+}
+
 int exynos_drm_gem_create_ioctl(struct drm_device *dev, void *data,
-               struct drm_file *file_priv)
+                                       struct drm_file *file_priv)
 {
        struct drm_exynos_gem_create *args = data;
-       struct exynos_drm_gem_obj *exynos_gem_obj;
+       struct exynos_drm_gem_obj *exynos_gem_obj = NULL;
 
-       DRM_DEBUG_KMS("%s : size = 0x%x\n", __FILE__, args->size);
+       DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size,
-                       &args->handle);
+       exynos_gem_obj = exynos_drm_gem_create(dev, file_priv,
+                                               &args->handle, args->size);
        if (IS_ERR(exynos_gem_obj))
                return PTR_ERR(exynos_gem_obj);
 
@@ -175,7 +189,7 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
 {
        struct drm_gem_object *obj = filp->private_data;
        struct exynos_drm_gem_obj *exynos_gem_obj = to_exynos_gem_obj(obj);
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
        unsigned long pfn, vm_size;
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -187,20 +201,20 @@ static int exynos_drm_gem_mmap_buffer(struct file *filp,
 
        vm_size = vma->vm_end - vma->vm_start;
        /*
-        * a entry contains information to physically continuous memory
+        * a buffer contains information to physically continuous memory
         * allocated by user request or at framebuffer creation.
         */
-       entry = exynos_gem_obj->entry;
+       buffer = exynos_gem_obj->buffer;
 
        /* check if user-requested size is valid. */
-       if (vm_size > entry->size)
+       if (vm_size > buffer->size)
                return -EINVAL;
 
        /*
         * get page frame number to physical memory to be mapped
         * to user space.
         */
-       pfn = exynos_gem_obj->entry->paddr >> PAGE_SHIFT;
+       pfn = ((unsigned long)exynos_gem_obj->buffer->dma_addr) >> PAGE_SHIFT;
 
        DRM_DEBUG_KMS("pfn = 0x%lx\n", pfn);
 
@@ -281,7 +295,7 @@ void exynos_drm_gem_free_object(struct drm_gem_object *gem_obj)
 
        exynos_gem_obj = to_exynos_gem_obj(gem_obj);
 
-       exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->entry);
+       exynos_drm_buf_destroy(gem_obj->dev, exynos_gem_obj->buffer);
 
        kfree(exynos_gem_obj);
 }
@@ -302,8 +316,8 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
        args->pitch = args->width * args->bpp >> 3;
        args->size = args->pitch * args->height;
 
-       exynos_gem_obj = exynos_drm_gem_create(file_priv, dev, args->size,
-                                                       &args->handle);
+       exynos_gem_obj = exynos_drm_gem_create(dev, file_priv, &args->handle,
+                                                       args->size);
        if (IS_ERR(exynos_gem_obj))
                return PTR_ERR(exynos_gem_obj);
 
@@ -360,7 +374,8 @@ int exynos_drm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
        mutex_lock(&dev->struct_mutex);
 
-       pfn = (exynos_gem_obj->entry->paddr >> PAGE_SHIFT) + page_offset;
+       pfn = (((unsigned long)exynos_gem_obj->buffer->dma_addr) >>
+                       PAGE_SHIFT) + page_offset;
 
        ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
 
index e5fc014..ef87973 100644 (file)
 #define to_exynos_gem_obj(x)   container_of(x,\
                        struct exynos_drm_gem_obj, base)
 
+/*
+ * exynos drm gem buffer structure.
+ *
+ * @kvaddr: kernel virtual address to allocated memory region.
+ * @dma_addr: bus address(accessed by dma) to allocated memory region.
+ *     - this address could be physical address without IOMMU and
+ *     device address with IOMMU.
+ * @size: size of allocated memory region.
+ */
+struct exynos_drm_gem_buf {
+       void __iomem            *kvaddr;
+       dma_addr_t              dma_addr;
+       unsigned long           size;
+};
+
 /*
  * exynos drm buffer structure.
  *
  * @base: a gem object.
  *     - a new handle to this gem object would be created
  *     by drm_gem_handle_create().
- * @entry: pointer to exynos drm buffer entry object.
- *     - containing the information to physically
+ * @buffer: a pointer to exynos_drm_gem_buffer object.
+ *     - contain the information to memory region allocated
+ *     by user request or at framebuffer creation.
  *     continuous memory region allocated by user request
  *     or at framebuffer creation.
  *
  */
 struct exynos_drm_gem_obj {
        struct drm_gem_object base;
-       struct exynos_drm_buf_entry *entry;
+       struct exynos_drm_gem_buf *buffer;
 };
 
 /* create a new buffer and get a new gem handle. */
-struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_file *file_priv,
-               struct drm_device *dev, unsigned int size,
-               unsigned int *handle);
+struct exynos_drm_gem_obj *exynos_drm_gem_create(struct drm_device *dev,
+               struct drm_file *file_priv,
+               unsigned int *handle, unsigned long size);
 
 /*
  * request gem object creation and buffer allocation as the size
index d14b44e..d09a6e0 100644 (file)
@@ -636,11 +636,16 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        struct intel_ring_buffer *ring;
+       int ret;
 
        ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
        if (ring->size == 0)
                return 0;
 
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
        seq_printf(m, "Ring %s:\n", ring->name);
        seq_printf(m, "  Head :    %08x\n", I915_READ_HEAD(ring) & HEAD_ADDR);
        seq_printf(m, "  Tail :    %08x\n", I915_READ_TAIL(ring) & TAIL_ADDR);
@@ -654,6 +659,8 @@ static int i915_ringbuffer_info(struct seq_file *m, void *data)
        seq_printf(m, "  Control : %08x\n", I915_READ_CTL(ring));
        seq_printf(m, "  Start :   %08x\n", I915_READ_START(ring));
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -842,7 +849,16 @@ static int i915_rstdby_delays(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u16 crstanddelay = I915_READ16(CRSTANDVID);
+       u16 crstanddelay;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       crstanddelay = I915_READ16(CRSTANDVID);
+
+       mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "w/ctx: %d, w/o ctx: %d\n", (crstanddelay >> 8) & 0x3f, (crstanddelay & 0x3f));
 
@@ -940,7 +956,11 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 delayfreq;
-       int i;
+       int ret, i;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
 
        for (i = 0; i < 16; i++) {
                delayfreq = I915_READ(PXVFREQ_BASE + i * 4);
@@ -948,6 +968,8 @@ static int i915_delayfreq_table(struct seq_file *m, void *unused)
                           (delayfreq & PXVFREQ_PX_MASK) >> PXVFREQ_PX_SHIFT);
        }
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -962,13 +984,19 @@ static int i915_inttoext_table(struct seq_file *m, void *unused)
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
        u32 inttoext;
-       int i;
+       int ret, i;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
 
        for (i = 1; i <= 32; i++) {
                inttoext = I915_READ(INTTOEXT_BASE_ILK + i * 4);
                seq_printf(m, "INTTOEXT%02d: 0x%08x\n", i, inttoext);
        }
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -977,9 +1005,19 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
-       u32 rgvmodectl = I915_READ(MEMMODECTL);
-       u32 rstdbyctl = I915_READ(RSTDBYCTL);
-       u16 crstandvid = I915_READ16(CRSTANDVID);
+       u32 rgvmodectl, rstdbyctl;
+       u16 crstandvid;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       rgvmodectl = I915_READ(MEMMODECTL);
+       rstdbyctl = I915_READ(RSTDBYCTL);
+       crstandvid = I915_READ16(CRSTANDVID);
+
+       mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "HD boost: %s\n", (rgvmodectl & MEMMODE_BOOST_EN) ?
                   "yes" : "no");
@@ -1167,9 +1205,16 @@ static int i915_gfxec(struct seq_file *m, void *unused)
        struct drm_info_node *node = (struct drm_info_node *) m->private;
        struct drm_device *dev = node->minor->dev;
        drm_i915_private_t *dev_priv = dev->dev_private;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
 
        seq_printf(m, "GFXEC: %ld\n", (unsigned long)I915_READ(0x112f4));
 
+       mutex_unlock(&dev->struct_mutex);
+
        return 0;
 }
 
@@ -1506,7 +1551,10 @@ drm_add_fake_info_node(struct drm_minor *minor,
        node->minor = minor;
        node->dent = ent;
        node->info_ent = (void *) key;
-       list_add(&node->list, &minor->debugfs_nodes.list);
+
+       mutex_lock(&minor->debugfs_lock);
+       list_add(&node->list, &minor->debugfs_list);
+       mutex_unlock(&minor->debugfs_lock);
 
        return 0;
 }
index cc531bb..15bfa91 100644 (file)
@@ -68,7 +68,7 @@ module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
 MODULE_PARM_DESC(i915_enable_rc6,
                "Enable power-saving render C-state 6 (default: true)");
 
-unsigned int i915_enable_fbc __read_mostly = -1;
+int i915_enable_fbc __read_mostly = -1;
 module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600);
 MODULE_PARM_DESC(i915_enable_fbc,
                "Enable frame buffer compression for power savings "
@@ -80,7 +80,7 @@ MODULE_PARM_DESC(lvds_downclock,
                "Use panel (LVDS/eDP) downclocking for power savings "
                "(default: false)");
 
-unsigned int i915_panel_use_ssc __read_mostly = -1;
+int i915_panel_use_ssc __read_mostly = -1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
 MODULE_PARM_DESC(lvds_use_ssc,
                "Use Spread Spectrum Clock with panels [LVDS/eDP] "
@@ -107,7 +107,7 @@ static struct drm_driver driver;
 extern int intel_agp_enabled;
 
 #define INTEL_VGA_DEVICE(id, info) {           \
-       .class = PCI_CLASS_DISPLAY_VGA << 8,    \
+       .class = PCI_BASE_CLASS_DISPLAY << 16,  \
        .class_mask = 0xff0000,                 \
        .vendor = 0x8086,                       \
        .device = id,                           \
@@ -789,8 +789,8 @@ static struct vm_operations_struct i915_gem_vm_ops = {
 };
 
 static struct drm_driver driver = {
-       /* don't use mtrr's here, the Xserver or user space app should
-        * deal with them for intel hardware.
+       /* Don't use MTRRs here; the Xserver or userspace app should
+        * deal with them for Intel hardware.
         */
        .driver_features =
            DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
index 06a37f4..4a9c1b9 100644 (file)
@@ -126,6 +126,9 @@ struct drm_i915_master_private {
        struct _drm_i915_sarea *sarea_priv;
 };
 #define I915_FENCE_REG_NONE -1
+#define I915_MAX_NUM_FENCES 16
+/* 16 fences + sign bit for FENCE_REG_NONE */
+#define I915_MAX_NUM_FENCE_BITS 5
 
 struct drm_i915_fence_reg {
        struct list_head lru_list;
@@ -168,7 +171,7 @@ struct drm_i915_error_state {
        u32 instdone1;
        u32 seqno;
        u64 bbaddr;
-       u64 fence[16];
+       u64 fence[I915_MAX_NUM_FENCES];
        struct timeval time;
        struct drm_i915_error_object {
                int page_count;
@@ -182,7 +185,7 @@ struct drm_i915_error_state {
                u32 gtt_offset;
                u32 read_domains;
                u32 write_domain;
-               s32 fence_reg:5;
+               s32 fence_reg:I915_MAX_NUM_FENCE_BITS;
                s32 pinned:2;
                u32 tiling:2;
                u32 dirty:1;
@@ -375,7 +378,7 @@ typedef struct drm_i915_private {
        struct notifier_block lid_notifier;
 
        int crt_ddc_pin;
-       struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
+       struct drm_i915_fence_reg fence_regs[I915_MAX_NUM_FENCES]; /* assume 965 */
        int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
        int num_fence_regs; /* 8 on pre-965, 16 otherwise */
 
@@ -506,7 +509,7 @@ typedef struct drm_i915_private {
        u8 saveAR[21];
        u8 saveDACMASK;
        u8 saveCR[37];
-       uint64_t saveFENCE[16];
+       uint64_t saveFENCE[I915_MAX_NUM_FENCES];
        u32 saveCURACNTR;
        u32 saveCURAPOS;
        u32 saveCURABASE;
@@ -777,10 +780,8 @@ struct drm_i915_gem_object {
         * Fence register bits (if any) for this object.  Will be set
         * as needed when mapped into the GTT.
         * Protected by dev->struct_mutex.
-        *
-        * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
         */
-       signed int fence_reg:5;
+       signed int fence_reg:I915_MAX_NUM_FENCE_BITS;
 
        /**
         * Advice: are the backing pages purgeable?
@@ -999,10 +1000,10 @@ extern int i915_panel_ignore_lid __read_mostly;
 extern unsigned int i915_powersave __read_mostly;
 extern unsigned int i915_semaphores __read_mostly;
 extern unsigned int i915_lvds_downclock __read_mostly;
-extern unsigned int i915_panel_use_ssc __read_mostly;
+extern int i915_panel_use_ssc __read_mostly;
 extern int i915_vbt_sdvo_panel_type __read_mostly;
 extern unsigned int i915_enable_rc6 __read_mostly;
-extern unsigned int i915_enable_fbc __read_mostly;
+extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
index 6651c36..8359dc7 100644 (file)
@@ -1396,7 +1396,7 @@ i915_gem_mmap_gtt(struct drm_file *file,
 
        if (obj->base.size > dev_priv->mm.gtt_mappable_end) {
                ret = -E2BIG;
-               goto unlock;
+               goto out;
        }
 
        if (obj->madv != I915_MADV_WILLNEED) {
@@ -1745,7 +1745,7 @@ static void i915_gem_reset_fences(struct drm_device *dev)
        struct drm_i915_private *dev_priv = dev->dev_private;
        int i;
 
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < dev_priv->num_fence_regs; i++) {
                struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
                struct drm_i915_gem_object *obj = reg->obj;
 
@@ -3512,9 +3512,11 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
                         * so emit a request to do so.
                         */
                        request = kzalloc(sizeof(*request), GFP_KERNEL);
-                       if (request)
+                       if (request) {
                                ret = i915_add_request(obj->ring, NULL, request);
-                       else
+                               if (ret)
+                                       kfree(request);
+                       } else
                                ret = -ENOMEM;
                }
 
@@ -3613,7 +3615,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
        obj->base.write_domain = I915_GEM_DOMAIN_CPU;
        obj->base.read_domains = I915_GEM_DOMAIN_CPU;
 
-       if (IS_GEN6(dev)) {
+       if (IS_GEN6(dev) || IS_GEN7(dev)) {
                /* On Gen6, we can have the GPU use the LLC (the CPU
                 * cache) for about a 10% performance improvement
                 * compared to uncached.  Graphics requests other than
@@ -3877,7 +3879,7 @@ i915_gem_load(struct drm_device *dev)
        INIT_LIST_HEAD(&dev_priv->mm.gtt_list);
        for (i = 0; i < I915_NUM_RINGS; i++)
                init_ring_lists(&dev_priv->ring[i]);
-       for (i = 0; i < 16; i++)
+       for (i = 0; i < I915_MAX_NUM_FENCES; i++)
                INIT_LIST_HEAD(&dev_priv->fence_regs[i].lru_list);
        INIT_DELAYED_WORK(&dev_priv->mm.retire_work,
                          i915_gem_retire_work_handler);
index 9ee2729..b40004b 100644 (file)
@@ -824,6 +824,7 @@ static void i915_gem_record_fences(struct drm_device *dev,
 
        /* Fences */
        switch (INTEL_INFO(dev)->gen) {
+       case 7:
        case 6:
                for (i = 0; i < 16; i++)
                        error->fence[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
index 5a09416..b080cc8 100644 (file)
  */
 #define   PP_READY             (1 << 30)
 #define   PP_SEQUENCE_NONE     (0 << 28)
-#define   PP_SEQUENCE_ON       (1 << 28)
-#define   PP_SEQUENCE_OFF      (2 << 28)
-#define   PP_SEQUENCE_MASK     0x30000000
+#define   PP_SEQUENCE_POWER_UP (1 << 28)
+#define   PP_SEQUENCE_POWER_DOWN (2 << 28)
+#define   PP_SEQUENCE_MASK     (3 << 28)
+#define   PP_SEQUENCE_SHIFT    28
 #define   PP_CYCLE_DELAY_ACTIVE        (1 << 27)
-#define   PP_SEQUENCE_STATE_ON_IDLE (1 << 3)
 #define   PP_SEQUENCE_STATE_MASK 0x0000000f
+#define   PP_SEQUENCE_STATE_OFF_IDLE   (0x0 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_1   (0x1 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_2   (0x2 << 0)
+#define   PP_SEQUENCE_STATE_OFF_S0_3   (0x3 << 0)
+#define   PP_SEQUENCE_STATE_ON_IDLE    (0x8 << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_0    (0x9 << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_2    (0xa << 0)
+#define   PP_SEQUENCE_STATE_ON_S1_3    (0xb << 0)
+#define   PP_SEQUENCE_STATE_RESET      (0xf << 0)
 #define PP_CONTROL     0x61204
 #define   POWER_TARGET_ON      (1 << 0)
 #define PP_ON_DELAYS   0x61208
 #define  GT_FIFO_FREE_ENTRIES                  0x120008
 #define    GT_FIFO_NUM_RESERVED_ENTRIES                20
 
+#define GEN6_UCGCTL2                           0x9404
+# define GEN6_RCPBUNIT_CLOCK_GATE_DISABLE              (1 << 12)
+# define GEN6_RCCUNIT_CLOCK_GATE_DISABLE               (1 << 11)
+
 #define GEN6_RPNSWREQ                          0xA008
 #define   GEN6_TURBO_DISABLE                   (1<<31)
 #define   GEN6_FREQUENCY(x)                    ((x)<<25)
index f8f602d..7886e4f 100644 (file)
@@ -370,6 +370,7 @@ static void i915_save_modeset_reg(struct drm_device *dev)
 
        /* Fences */
        switch (INTEL_INFO(dev)->gen) {
+       case 7:
        case 6:
                for (i = 0; i < 16; i++)
                        dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_SANDYBRIDGE_0 + (i * 8));
@@ -404,6 +405,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)
 
        /* Fences */
        switch (INTEL_INFO(dev)->gen) {
+       case 7:
        case 6:
                for (i = 0; i < 16; i++)
                        I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), dev_priv->saveFENCE[i]);
index 981b1f1..e77a863 100644 (file)
@@ -2933,7 +2933,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)
 
        /* For PCH DP, enable TRANS_DP_CTL */
        if (HAS_PCH_CPT(dev) &&
-           intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {
+           (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+            intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) {
                u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5;
                reg = TRANS_DP_CTL(pipe);
                temp = I915_READ(reg);
@@ -4711,7 +4712,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                                lvds_bpc = 6;
 
                        if (lvds_bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to LVDS (%d)\n", display_bpc, lvds_bpc);
                                display_bpc = lvds_bpc;
                        }
                        continue;
@@ -4722,7 +4723,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        unsigned int edp_bpc = dev_priv->edp.bpp / 3;
 
                        if (edp_bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
                                display_bpc = edp_bpc;
                        }
                        continue;
@@ -4737,7 +4738,7 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        /* Don't use an invalid EDID bpc value */
                        if (connector->display_info.bpc &&
                            connector->display_info.bpc < display_bpc) {
-                               DRM_DEBUG_DRIVER("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to EDID reported max of %d\n", display_bpc, connector->display_info.bpc);
                                display_bpc = connector->display_info.bpc;
                        }
                }
@@ -4748,10 +4749,10 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                 */
                if (intel_encoder->type == INTEL_OUTPUT_HDMI) {
                        if (display_bpc > 8 && display_bpc < 12) {
-                               DRM_DEBUG_DRIVER("forcing bpc to 12 for HDMI\n");
+                               DRM_DEBUG_KMS("forcing bpc to 12 for HDMI\n");
                                display_bpc = 12;
                        } else {
-                               DRM_DEBUG_DRIVER("forcing bpc to 8 for HDMI\n");
+                               DRM_DEBUG_KMS("forcing bpc to 8 for HDMI\n");
                                display_bpc = 8;
                        }
                }
@@ -4789,8 +4790,8 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
 
        display_bpc = min(display_bpc, bpc);
 
-       DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n",
-                        bpc, display_bpc);
+       DRM_DEBUG_KMS("setting pipe bpc to %d (max display bpc %d)\n",
+                     bpc, display_bpc);
 
        *pipe_bpp = display_bpc * 3;
 
@@ -5671,7 +5672,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
        pipeconf &= ~PIPECONF_DITHER_TYPE_MASK;
        if ((is_lvds && dev_priv->lvds_dither) || dither) {
                pipeconf |= PIPECONF_DITHER_EN;
-               pipeconf |= PIPECONF_DITHER_TYPE_ST1;
+               pipeconf |= PIPECONF_DITHER_TYPE_SP;
        }
        if (is_dp || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
                intel_dp_set_m_n(crtc, mode, adjusted_mode);
@@ -8148,6 +8149,20 @@ static void gen6_init_clock_gating(struct drm_device *dev)
        I915_WRITE(WM2_LP_ILK, 0);
        I915_WRITE(WM1_LP_ILK, 0);
 
+       /* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock
+        * gating disable must be set.  Failure to set it results in
+        * flickering pixels due to Z write ordering failures after
+        * some amount of runtime in the Mesa "fire" demo, and Unigine
+        * Sanctuary and Tropics, and apparently anything else with
+        * alpha test or pixel discard.
+        *
+        * According to the spec, bit 11 (RCCUNIT) must also be set,
+        * but we didn't debug actual testcases to find it out.
+        */
+       I915_WRITE(GEN6_UCGCTL2,
+                  GEN6_RCPBUNIT_CLOCK_GATE_DISABLE |
+                  GEN6_RCCUNIT_CLOCK_GATE_DISABLE);
+
        /*
         * According to the spec the following bits should be
         * set in order to enable memory self-refresh and fbc:
index 09b318b..4d0358f 100644 (file)
@@ -59,7 +59,6 @@ struct intel_dp {
        struct i2c_algo_dp_aux_data algo;
        bool is_pch_edp;
        uint8_t train_set[4];
-       uint8_t link_status[DP_LINK_STATUS_SIZE];
        int panel_power_up_delay;
        int panel_power_down_delay;
        int panel_power_cycle_delay;
@@ -68,7 +67,6 @@ struct intel_dp {
        struct drm_display_mode *panel_fixed_mode;  /* for eDP */
        struct delayed_work panel_vdd_work;
        bool want_panel_vdd;
-       unsigned long panel_off_jiffies;
 };
 
 /**
@@ -157,16 +155,12 @@ intel_edp_link_config(struct intel_encoder *intel_encoder,
 static int
 intel_dp_max_lane_count(struct intel_dp *intel_dp)
 {
-       int max_lane_count = 4;
-
-       if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) {
-               max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
-               switch (max_lane_count) {
-               case 1: case 2: case 4:
-                       break;
-               default:
-                       max_lane_count = 4;
-               }
+       int max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;
+       switch (max_lane_count) {
+       case 1: case 2: case 4:
+               break;
+       default:
+               max_lane_count = 4;
        }
        return max_lane_count;
 }
@@ -768,12 +762,11 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                        continue;
 
                intel_dp = enc_to_intel_dp(encoder);
-               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT) {
+               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
+                   intel_dp->base.type == INTEL_OUTPUT_EDP)
+               {
                        lane_count = intel_dp->lane_count;
                        break;
-               } else if (is_edp(intel_dp)) {
-                       lane_count = dev_priv->edp.lanes;
-                       break;
                }
        }
 
@@ -810,6 +803,7 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                  struct drm_display_mode *adjusted_mode)
 {
        struct drm_device *dev = encoder->dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
        struct drm_crtc *crtc = intel_dp->base.base.crtc;
        struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
@@ -822,18 +816,31 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                        ironlake_edp_pll_off(encoder);
        }
 
-       intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
-       intel_dp->DP |= intel_dp->color_range;
+       /*
+        * There are three kinds of DP registers:
+        *
+        *      IBX PCH
+        *      CPU
+        *      CPT PCH
+        *
+        * IBX PCH and CPU are the same for almost everything,
+        * except that the CPU DP PLL is configured in this
+        * register
+        *
+        * CPT PCH is quite different, having many bits moved
+        * to the TRANS_DP_CTL register instead. That
+        * configuration happens (oddly) in ironlake_pch_enable
+        */
 
-       if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-               intel_dp->DP |= DP_SYNC_HS_HIGH;
-       if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-               intel_dp->DP |= DP_SYNC_VS_HIGH;
+       /* Preserve the BIOS-computed detected bit. This is
+        * supposed to be read-only.
+        */
+       intel_dp->DP = I915_READ(intel_dp->output_reg) & DP_DETECTED;
+       intel_dp->DP |=  DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
-       if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
-               intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
-       else
-               intel_dp->DP |= DP_LINK_TRAIN_OFF;
+       /* Handle DP bits in common between all three register formats */
+
+       intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
 
        switch (intel_dp->lane_count) {
        case 1:
@@ -852,59 +859,106 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                intel_dp->DP |= DP_AUDIO_OUTPUT_ENABLE;
                intel_write_eld(encoder, adjusted_mode);
        }
-
        memset(intel_dp->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE);
        intel_dp->link_configuration[0] = intel_dp->link_bw;
        intel_dp->link_configuration[1] = intel_dp->lane_count;
        intel_dp->link_configuration[8] = DP_SET_ANSI_8B10B;
-
        /*
         * Check for DPCD version > 1.1 and enhanced framing support
         */
        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
            (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {
                intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
-               intel_dp->DP |= DP_ENHANCED_FRAMING;
        }
 
-       /* CPT DP's pipe select is decided in TRANS_DP_CTL */
-       if (intel_crtc->pipe == 1 && !HAS_PCH_CPT(dev))
-               intel_dp->DP |= DP_PIPEB_SELECT;
+       /* Split out the IBX/CPU vs CPT settings */
 
-       if (is_cpu_edp(intel_dp)) {
-               /* don't miss out required setting for eDP */
-               intel_dp->DP |= DP_PLL_ENABLE;
-               if (adjusted_mode->clock < 200000)
-                       intel_dp->DP |= DP_PLL_FREQ_160MHZ;
-               else
-                       intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+       if (!HAS_PCH_CPT(dev) || is_cpu_edp(intel_dp)) {
+               intel_dp->DP |= intel_dp->color_range;
+
+               if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+                       intel_dp->DP |= DP_SYNC_HS_HIGH;
+               if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+                       intel_dp->DP |= DP_SYNC_VS_HIGH;
+               intel_dp->DP |= DP_LINK_TRAIN_OFF;
+
+               if (intel_dp->link_configuration[1] & DP_LANE_COUNT_ENHANCED_FRAME_EN)
+                       intel_dp->DP |= DP_ENHANCED_FRAMING;
+
+               if (intel_crtc->pipe == 1)
+                       intel_dp->DP |= DP_PIPEB_SELECT;
+
+               if (is_cpu_edp(intel_dp)) {
+                       /* don't miss out required setting for eDP */
+                       intel_dp->DP |= DP_PLL_ENABLE;
+                       if (adjusted_mode->clock < 200000)
+                               intel_dp->DP |= DP_PLL_FREQ_160MHZ;
+                       else
+                               intel_dp->DP |= DP_PLL_FREQ_270MHZ;
+               }
+       } else {
+               intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
        }
 }
 
-static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
+#define IDLE_ON_MASK           (PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_ON_VALUE          (PP_ON | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
+
+#define IDLE_OFF_MASK          (PP_ON | 0        | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_OFF_VALUE         (0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+#define IDLE_CYCLE_MASK                (PP_ON | 0        | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
+#define IDLE_CYCLE_VALUE       (0     | 0        | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+static void ironlake_wait_panel_status(struct intel_dp *intel_dp,
+                                      u32 mask,
+                                      u32 value)
 {
-       unsigned long   off_time;
-       unsigned long   delay;
+       struct drm_device *dev = intel_dp->base.base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
 
-       DRM_DEBUG_KMS("Wait for panel power off time\n");
+       DRM_DEBUG_KMS("mask %08x value %08x status %08x control %08x\n",
+                     mask, value,
+                     I915_READ(PCH_PP_STATUS),
+                     I915_READ(PCH_PP_CONTROL));
 
-       if (ironlake_edp_have_panel_power(intel_dp) ||
-           ironlake_edp_have_panel_vdd(intel_dp))
-       {
-               DRM_DEBUG_KMS("Panel still on, no delay needed\n");
-               return;
+       if (_wait_for((I915_READ(PCH_PP_STATUS) & mask) == value, 5000, 10)) {
+               DRM_ERROR("Panel status timeout: status %08x control %08x\n",
+                         I915_READ(PCH_PP_STATUS),
+                         I915_READ(PCH_PP_CONTROL));
        }
+}
 
-       off_time = intel_dp->panel_off_jiffies + msecs_to_jiffies(intel_dp->panel_power_down_delay);
-       if (time_after(jiffies, off_time)) {
-               DRM_DEBUG_KMS("Time already passed");
-               return;
-       }
-       delay = jiffies_to_msecs(off_time - jiffies);
-       if (delay > intel_dp->panel_power_down_delay)
-               delay = intel_dp->panel_power_down_delay;
-       DRM_DEBUG_KMS("Waiting an additional %ld ms\n", delay);
-       msleep(delay);
+static void ironlake_wait_panel_on(struct intel_dp *intel_dp)
+{
+       DRM_DEBUG_KMS("Wait for panel power on\n");
+       ironlake_wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
+}
+
+static void ironlake_wait_panel_off(struct intel_dp *intel_dp)
+{
+       DRM_DEBUG_KMS("Wait for panel power off time\n");
+       ironlake_wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
+}
+
+static void ironlake_wait_panel_power_cycle(struct intel_dp *intel_dp)
+{
+       DRM_DEBUG_KMS("Wait for panel power cycle\n");
+       ironlake_wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
+}
+
+
+/* Read the current pp_control value, unlocking the register if it
+ * is locked
+ */
+
+static  u32 ironlake_get_pp_control(struct drm_i915_private *dev_priv)
+{
+       u32     control = I915_READ(PCH_PP_CONTROL);
+
+       control &= ~PANEL_UNLOCK_MASK;
+       control |= PANEL_UNLOCK_REGS;
+       return control;
 }
 
 static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
@@ -921,15 +975,16 @@ static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
             "eDP VDD already requested on\n");
 
        intel_dp->want_panel_vdd = true;
+
        if (ironlake_edp_have_panel_vdd(intel_dp)) {
                DRM_DEBUG_KMS("eDP VDD already on\n");
                return;
        }
 
-       ironlake_wait_panel_off(intel_dp);
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
+       if (!ironlake_edp_have_panel_power(intel_dp))
+               ironlake_wait_panel_power_cycle(intel_dp);
+
+       pp = ironlake_get_pp_control(dev_priv);
        pp |= EDP_FORCE_VDD;
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
@@ -952,9 +1007,7 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
        u32 pp;
 
        if (!intel_dp->want_panel_vdd && ironlake_edp_have_panel_vdd(intel_dp)) {
-               pp = I915_READ(PCH_PP_CONTROL);
-               pp &= ~PANEL_UNLOCK_MASK;
-               pp |= PANEL_UNLOCK_REGS;
+               pp = ironlake_get_pp_control(dev_priv);
                pp &= ~EDP_FORCE_VDD;
                I915_WRITE(PCH_PP_CONTROL, pp);
                POSTING_READ(PCH_PP_CONTROL);
@@ -962,7 +1015,8 @@ static void ironlake_panel_vdd_off_sync(struct intel_dp *intel_dp)
                /* Make sure sequencer is idle before allowing subsequent activity */
                DRM_DEBUG_KMS("PCH_PP_STATUS: 0x%08x PCH_PP_CONTROL: 0x%08x\n",
                              I915_READ(PCH_PP_STATUS), I915_READ(PCH_PP_CONTROL));
-               intel_dp->panel_off_jiffies = jiffies;
+
+               msleep(intel_dp->panel_power_down_delay);
        }
 }
 
@@ -972,9 +1026,9 @@ static void ironlake_panel_vdd_work(struct work_struct *__work)
                                                 struct intel_dp, panel_vdd_work);
        struct drm_device *dev = intel_dp->base.base.dev;
 
-       mutex_lock(&dev->struct_mutex);
+       mutex_lock(&dev->mode_config.mutex);
        ironlake_panel_vdd_off_sync(intel_dp);
-       mutex_unlock(&dev->struct_mutex);
+       mutex_unlock(&dev->mode_config.mutex);
 }
 
 static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
@@ -984,7 +1038,7 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 
        DRM_DEBUG_KMS("Turn eDP VDD off %d\n", intel_dp->want_panel_vdd);
        WARN(!intel_dp->want_panel_vdd, "eDP VDD not forced on");
-       
+
        intel_dp->want_panel_vdd = false;
 
        if (sync) {
@@ -1000,23 +1054,25 @@ static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
        }
 }
 
-/* Returns true if the panel was already on when called */
 static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
 {
        struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp, idle_on_mask = PP_ON | PP_SEQUENCE_STATE_ON_IDLE;
+       u32 pp;
 
        if (!is_edp(intel_dp))
                return;
-       if (ironlake_edp_have_panel_power(intel_dp))
+
+       DRM_DEBUG_KMS("Turn eDP power on\n");
+
+       if (ironlake_edp_have_panel_power(intel_dp)) {
+               DRM_DEBUG_KMS("eDP power already on\n");
                return;
+       }
 
-       ironlake_wait_panel_off(intel_dp);
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
+       ironlake_wait_panel_power_cycle(intel_dp);
 
+       pp = ironlake_get_pp_control(dev_priv);
        if (IS_GEN5(dev)) {
                /* ILK workaround: disable reset around power sequence */
                pp &= ~PANEL_POWER_RESET;
@@ -1025,13 +1081,13 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
        }
 
        pp |= POWER_TARGET_ON;
+       if (!IS_GEN5(dev))
+               pp |= PANEL_POWER_RESET;
+
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
 
-       if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask,
-                    5000))
-               DRM_ERROR("panel on wait timed out: 0x%08x\n",
-                         I915_READ(PCH_PP_STATUS));
+       ironlake_wait_panel_on(intel_dp);
 
        if (IS_GEN5(dev)) {
                pp |= PANEL_POWER_RESET; /* restore panel reset bit */
@@ -1040,46 +1096,25 @@ static void ironlake_edp_panel_on(struct intel_dp *intel_dp)
        }
 }
 
-static void ironlake_edp_panel_off(struct drm_encoder *encoder)
+static void ironlake_edp_panel_off(struct intel_dp *intel_dp)
 {
-       struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-       struct drm_device *dev = encoder->dev;
+       struct drm_device *dev = intel_dp->base.base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 pp, idle_off_mask = PP_ON | PP_SEQUENCE_MASK |
-               PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK;
+       u32 pp;
 
        if (!is_edp(intel_dp))
                return;
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
 
-       if (IS_GEN5(dev)) {
-               /* ILK workaround: disable reset around power sequence */
-               pp &= ~PANEL_POWER_RESET;
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
-       }
+       DRM_DEBUG_KMS("Turn eDP power off\n");
 
-       intel_dp->panel_off_jiffies = jiffies;
+       WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n");
 
-       if (IS_GEN5(dev)) {
-               pp &= ~POWER_TARGET_ON;
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
-               pp &= ~POWER_TARGET_ON;
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
-               msleep(intel_dp->panel_power_cycle_delay);
-
-               if (wait_for((I915_READ(PCH_PP_STATUS) & idle_off_mask) == 0, 5000))
-                       DRM_ERROR("panel off wait timed out: 0x%08x\n",
-                                 I915_READ(PCH_PP_STATUS));
+       pp = ironlake_get_pp_control(dev_priv);
+       pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE);
+       I915_WRITE(PCH_PP_CONTROL, pp);
+       POSTING_READ(PCH_PP_CONTROL);
 
-               pp |= PANEL_POWER_RESET; /* restore panel reset bit */
-               I915_WRITE(PCH_PP_CONTROL, pp);
-               POSTING_READ(PCH_PP_CONTROL);
-       }
+       ironlake_wait_panel_off(intel_dp);
 }
 
 static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
@@ -1099,9 +1134,7 @@ static void ironlake_edp_backlight_on(struct intel_dp *intel_dp)
         * allowing it to appear.
         */
        msleep(intel_dp->backlight_on_delay);
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
+       pp = ironlake_get_pp_control(dev_priv);
        pp |= EDP_BLC_ENABLE;
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
@@ -1117,9 +1150,7 @@ static void ironlake_edp_backlight_off(struct intel_dp *intel_dp)
                return;
 
        DRM_DEBUG_KMS("\n");
-       pp = I915_READ(PCH_PP_CONTROL);
-       pp &= ~PANEL_UNLOCK_MASK;
-       pp |= PANEL_UNLOCK_REGS;
+       pp = ironlake_get_pp_control(dev_priv);
        pp &= ~EDP_BLC_ENABLE;
        I915_WRITE(PCH_PP_CONTROL, pp);
        POSTING_READ(PCH_PP_CONTROL);
@@ -1187,17 +1218,18 @@ static void intel_dp_prepare(struct drm_encoder *encoder)
 {
        struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
+       ironlake_edp_backlight_off(intel_dp);
+       ironlake_edp_panel_off(intel_dp);
+
        /* Wake up the sink first */
        ironlake_edp_panel_vdd_on(intel_dp);
        intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
+       intel_dp_link_down(intel_dp);
        ironlake_edp_panel_vdd_off(intel_dp, false);
 
        /* Make sure the panel is off before trying to
         * change the mode
         */
-       ironlake_edp_backlight_off(intel_dp);
-       intel_dp_link_down(intel_dp);
-       ironlake_edp_panel_off(encoder);
 }
 
 static void intel_dp_commit(struct drm_encoder *encoder)
@@ -1211,7 +1243,6 @@ static void intel_dp_commit(struct drm_encoder *encoder)
        intel_dp_start_link_train(intel_dp);
        ironlake_edp_panel_on(intel_dp);
        ironlake_edp_panel_vdd_off(intel_dp, true);
-
        intel_dp_complete_link_train(intel_dp);
        ironlake_edp_backlight_on(intel_dp);
 
@@ -1230,16 +1261,20 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
        uint32_t dp_reg = I915_READ(intel_dp->output_reg);
 
        if (mode != DRM_MODE_DPMS_ON) {
+               ironlake_edp_backlight_off(intel_dp);
+               ironlake_edp_panel_off(intel_dp);
+
                ironlake_edp_panel_vdd_on(intel_dp);
-               if (is_edp(intel_dp))
-                       ironlake_edp_backlight_off(intel_dp);
                intel_dp_sink_dpms(intel_dp, mode);
                intel_dp_link_down(intel_dp);
-               ironlake_edp_panel_off(encoder);
-               if (is_edp(intel_dp) && !is_pch_edp(intel_dp))
-                       ironlake_edp_pll_off(encoder);
                ironlake_edp_panel_vdd_off(intel_dp, false);
+
+               if (is_cpu_edp(intel_dp))
+                       ironlake_edp_pll_off(encoder);
        } else {
+               if (is_cpu_edp(intel_dp))
+                       ironlake_edp_pll_on(encoder);
+
                ironlake_edp_panel_vdd_on(intel_dp);
                intel_dp_sink_dpms(intel_dp, mode);
                if (!(dp_reg & DP_PORT_EN)) {
@@ -1247,7 +1282,6 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
                        ironlake_edp_panel_on(intel_dp);
                        ironlake_edp_panel_vdd_off(intel_dp, true);
                        intel_dp_complete_link_train(intel_dp);
-                       ironlake_edp_backlight_on(intel_dp);
                } else
                        ironlake_edp_panel_vdd_off(intel_dp, false);
                ironlake_edp_backlight_on(intel_dp);
@@ -1285,11 +1319,11 @@ intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address,
  * link status information
  */
 static bool
-intel_dp_get_link_status(struct intel_dp *intel_dp)
+intel_dp_get_link_status(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
        return intel_dp_aux_native_read_retry(intel_dp,
                                              DP_LANE0_1_STATUS,
-                                             intel_dp->link_status,
+                                             link_status,
                                              DP_LINK_STATUS_SIZE);
 }
 
@@ -1301,27 +1335,25 @@ intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
 }
 
 static uint8_t
-intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE],
+intel_get_adjust_request_voltage(uint8_t adjust_request[2],
                                 int lane)
 {
-       int         i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
        int         s = ((lane & 1) ?
                         DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT :
                         DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT);
-       uint8_t l = intel_dp_link_status(link_status, i);
+       uint8_t l = adjust_request[lane>>1];
 
        return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT;
 }
 
 static uint8_t
-intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE],
+intel_get_adjust_request_pre_emphasis(uint8_t adjust_request[2],
                                      int lane)
 {
-       int         i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1);
        int         s = ((lane & 1) ?
                         DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT :
                         DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT);
-       uint8_t l = intel_dp_link_status(link_status, i);
+       uint8_t l = adjust_request[lane>>1];
 
        return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT;
 }
@@ -1344,6 +1376,7 @@ static char       *link_train_names[] = {
  * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB
  */
 #define I830_DP_VOLTAGE_MAX        DP_TRAIN_VOLTAGE_SWING_800
+#define I830_DP_VOLTAGE_MAX_CPT            DP_TRAIN_VOLTAGE_SWING_1200
 
 static uint8_t
 intel_dp_pre_emphasis_max(uint8_t voltage_swing)
@@ -1362,15 +1395,18 @@ intel_dp_pre_emphasis_max(uint8_t voltage_swing)
 }
 
 static void
-intel_get_adjust_train(struct intel_dp *intel_dp)
+intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
+       struct drm_device *dev = intel_dp->base.base.dev;
        uint8_t v = 0;
        uint8_t p = 0;
        int lane;
+       uint8_t *adjust_request = link_status + (DP_ADJUST_REQUEST_LANE0_1 - DP_LANE0_1_STATUS);
+       int voltage_max;
 
        for (lane = 0; lane < intel_dp->lane_count; lane++) {
-               uint8_t this_v = intel_get_adjust_request_voltage(intel_dp->link_status, lane);
-               uint8_t this_p = intel_get_adjust_request_pre_emphasis(intel_dp->link_status, lane);
+               uint8_t this_v = intel_get_adjust_request_voltage(adjust_request, lane);
+               uint8_t this_p = intel_get_adjust_request_pre_emphasis(adjust_request, lane);
 
                if (this_v > v)
                        v = this_v;
@@ -1378,8 +1414,12 @@ intel_get_adjust_train(struct intel_dp *intel_dp)
                        p = this_p;
        }
 
-       if (v >= I830_DP_VOLTAGE_MAX)
-               v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED;
+       if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
+               voltage_max = I830_DP_VOLTAGE_MAX_CPT;
+       else
+               voltage_max = I830_DP_VOLTAGE_MAX;
+       if (v >= voltage_max)
+               v = voltage_max | DP_TRAIN_MAX_SWING_REACHED;
 
        if (p >= intel_dp_pre_emphasis_max(v))
                p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED;
@@ -1389,7 +1429,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp)
 }
 
 static uint32_t
-intel_dp_signal_levels(uint8_t train_set, int lane_count)
+intel_dp_signal_levels(uint8_t train_set)
 {
        uint32_t        signal_levels = 0;
 
@@ -1458,9 +1498,8 @@ static uint8_t
 intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE],
                      int lane)
 {
-       int i = DP_LANE0_1_STATUS + (lane >> 1);
        int s = (lane & 1) * 4;
-       uint8_t l = intel_dp_link_status(link_status, i);
+       uint8_t l = link_status[lane>>1];
 
        return (l >> s) & 0xf;
 }
@@ -1485,18 +1524,18 @@ intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count
                         DP_LANE_CHANNEL_EQ_DONE|\
                         DP_LANE_SYMBOL_LOCKED)
 static bool
-intel_channel_eq_ok(struct intel_dp *intel_dp)
+intel_channel_eq_ok(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_STATUS_SIZE])
 {
        uint8_t lane_align;
        uint8_t lane_status;
        int lane;
 
-       lane_align = intel_dp_link_status(intel_dp->link_status,
+       lane_align = intel_dp_link_status(link_status,
                                          DP_LANE_ALIGN_STATUS_UPDATED);
        if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0)
                return false;
        for (lane = 0; lane < intel_dp->lane_count; lane++) {
-               lane_status = intel_get_lane_status(intel_dp->link_status, lane);
+               lane_status = intel_get_lane_status(link_status, lane);
                if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS)
                        return false;
        }
@@ -1521,8 +1560,9 @@ intel_dp_set_link_train(struct intel_dp *intel_dp,
 
        ret = intel_dp_aux_native_write(intel_dp,
                                        DP_TRAINING_LANE0_SET,
-                                       intel_dp->train_set, 4);
-       if (ret != 4)
+                                       intel_dp->train_set,
+                                       intel_dp->lane_count);
+       if (ret != intel_dp->lane_count)
                return false;
 
        return true;
@@ -1538,7 +1578,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
        int i;
        uint8_t voltage;
        bool clock_recovery = false;
-       int tries;
+       int voltage_tries, loop_tries;
        u32 reg;
        uint32_t DP = intel_dp->DP;
 
@@ -1565,16 +1605,20 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                DP &= ~DP_LINK_TRAIN_MASK;
        memset(intel_dp->train_set, 0, 4);
        voltage = 0xff;
-       tries = 0;
+       voltage_tries = 0;
+       loop_tries = 0;
        clock_recovery = false;
        for (;;) {
                /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
+               uint8_t     link_status[DP_LINK_STATUS_SIZE];
                uint32_t    signal_levels;
-               if (IS_GEN6(dev) && is_edp(intel_dp)) {
+
+               if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
                        signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
-                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
+                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
+                       DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", signal_levels);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
@@ -1590,10 +1634,13 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                /* Set training pattern 1 */
 
                udelay(100);
-               if (!intel_dp_get_link_status(intel_dp))
+               if (!intel_dp_get_link_status(intel_dp, link_status)) {
+                       DRM_ERROR("failed to get link status\n");
                        break;
+               }
 
-               if (intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+               if (intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
+                       DRM_DEBUG_KMS("clock recovery OK\n");
                        clock_recovery = true;
                        break;
                }
@@ -1602,20 +1649,30 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                for (i = 0; i < intel_dp->lane_count; i++)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
-               if (i == intel_dp->lane_count)
-                       break;
+               if (i == intel_dp->lane_count) {
+                       ++loop_tries;
+                       if (loop_tries == 5) {
+                               DRM_DEBUG_KMS("too many full retries, give up\n");
+                               break;
+                       }
+                       memset(intel_dp->train_set, 0, 4);
+                       voltage_tries = 0;
+                       continue;
+               }
 
                /* Check to see if we've tried the same voltage 5 times */
                if ((intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) {
-                       ++tries;
-                       if (tries == 5)
+                       ++voltage_tries;
+                       if (voltage_tries == 5) {
+                               DRM_DEBUG_KMS("too many voltage retries, give up\n");
                                break;
+                       }
                } else
-                       tries = 0;
+                       voltage_tries = 0;
                voltage = intel_dp->train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK;
 
                /* Compute new intel_dp->train_set as requested by target */
-               intel_get_adjust_train(intel_dp);
+               intel_get_adjust_train(intel_dp, link_status);
        }
 
        intel_dp->DP = DP;
@@ -1638,6 +1695,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
        for (;;) {
                /* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */
                uint32_t    signal_levels;
+               uint8_t     link_status[DP_LINK_STATUS_SIZE];
 
                if (cr_tries > 5) {
                        DRM_ERROR("failed to train DP, aborting\n");
@@ -1645,11 +1703,11 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                        break;
                }
 
-               if (IS_GEN6(dev) && is_edp(intel_dp)) {
+               if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) {
                        signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels;
                } else {
-                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0], intel_dp->lane_count);
+                       signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]);
                        DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels;
                }
 
@@ -1665,17 +1723,17 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                        break;
 
                udelay(400);
-               if (!intel_dp_get_link_status(intel_dp))
+               if (!intel_dp_get_link_status(intel_dp, link_status))
                        break;
 
                /* Make sure clock is still ok */
-               if (!intel_clock_recovery_ok(intel_dp->link_status, intel_dp->lane_count)) {
+               if (!intel_clock_recovery_ok(link_status, intel_dp->lane_count)) {
                        intel_dp_start_link_train(intel_dp);
                        cr_tries++;
                        continue;
                }
 
-               if (intel_channel_eq_ok(intel_dp)) {
+               if (intel_channel_eq_ok(intel_dp, link_status)) {
                        channel_eq = true;
                        break;
                }
@@ -1690,7 +1748,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)
                }
 
                /* Compute new intel_dp->train_set as requested by target */
-               intel_get_adjust_train(intel_dp);
+               intel_get_adjust_train(intel_dp, link_status);
                ++tries;
        }
 
@@ -1735,8 +1793,12 @@ intel_dp_link_down(struct intel_dp *intel_dp)
 
        msleep(17);
 
-       if (is_edp(intel_dp))
-               DP |= DP_LINK_TRAIN_OFF;
+       if (is_edp(intel_dp)) {
+               if (HAS_PCH_CPT(dev) && !is_cpu_edp(intel_dp))
+                       DP |= DP_LINK_TRAIN_OFF_CPT;
+               else
+                       DP |= DP_LINK_TRAIN_OFF;
+       }
 
        if (!HAS_PCH_CPT(dev) &&
            I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
@@ -1822,6 +1884,7 @@ static void
 intel_dp_check_link_status(struct intel_dp *intel_dp)
 {
        u8 sink_irq_vector;
+       u8 link_status[DP_LINK_STATUS_SIZE];
 
        if (intel_dp->dpms_mode != DRM_MODE_DPMS_ON)
                return;
@@ -1830,7 +1893,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
                return;
 
        /* Try to read receiver status if the link appears to be up */
-       if (!intel_dp_get_link_status(intel_dp)) {
+       if (!intel_dp_get_link_status(intel_dp, link_status)) {
                intel_dp_link_down(intel_dp);
                return;
        }
@@ -1855,7 +1918,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
                        DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
        }
 
-       if (!intel_channel_eq_ok(intel_dp)) {
+       if (!intel_channel_eq_ok(intel_dp, link_status)) {
                DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
                              drm_get_encoder_name(&intel_dp->base.base));
                intel_dp_start_link_train(intel_dp);
@@ -2179,7 +2242,8 @@ intel_trans_dp_port_sel(struct drm_crtc *crtc)
                        continue;
 
                intel_dp = enc_to_intel_dp(encoder);
-               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT)
+               if (intel_dp->base.type == INTEL_OUTPUT_DISPLAYPORT ||
+                   intel_dp->base.type == INTEL_OUTPUT_EDP)
                        return intel_dp->output_reg;
        }
 
@@ -2321,7 +2385,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
                cur.t8 = (pp_on & PANEL_LIGHT_ON_DELAY_MASK) >>
                        PANEL_LIGHT_ON_DELAY_SHIFT;
-               
+
                cur.t9 = (pp_off & PANEL_LIGHT_OFF_DELAY_MASK) >>
                        PANEL_LIGHT_OFF_DELAY_SHIFT;
 
@@ -2354,11 +2418,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
                              intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
 
-               intel_dp->panel_off_jiffies = jiffies - intel_dp->panel_power_down_delay;
-
                ironlake_edp_panel_vdd_on(intel_dp);
                ret = intel_dp_get_dpcd(intel_dp);
                ironlake_edp_panel_vdd_off(intel_dp, false);
+
                if (ret) {
                        if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11)
                                dev_priv->no_aux_handshake =
index 499d4c0..21f60b7 100644 (file)
@@ -326,7 +326,8 @@ static int intel_panel_update_status(struct backlight_device *bd)
 static int intel_panel_get_brightness(struct backlight_device *bd)
 {
        struct drm_device *dev = bl_get_data(bd);
-       return intel_panel_get_backlight(dev);
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       return dev_priv->backlight_level;
 }
 
 static const struct backlight_ops intel_panel_bl_ops = {
index 032a820..5fc201b 100644 (file)
@@ -640,10 +640,9 @@ static int
 nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
-       uint32_t reg0 = nv_rd32(dev, reg + 0);
-       uint32_t reg1 = nv_rd32(dev, reg + 4);
        struct nouveau_pll_vals pll;
        struct pll_lims pll_limits;
+       u32 ctrl, mask, coef;
        int ret;
 
        ret = get_pll_limits(dev, reg, &pll_limits);
@@ -654,15 +653,20 @@ nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
        if (!clk)
                return -ERANGE;
 
-       reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
-       reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
-
-       if (dev_priv->vbios.execute) {
-               still_alive();
-               nv_wr32(dev, reg + 4, reg1);
-               nv_wr32(dev, reg + 0, reg0);
+       coef = pll.N1 << 8 | pll.M1;
+       ctrl = pll.log2P << 16;
+       mask = 0x00070000;
+       if (reg == 0x004008) {
+               mask |= 0x01f80000;
+               ctrl |= (pll_limits.log2p_bias << 19);
+               ctrl |= (pll.log2P << 22);
        }
 
+       if (!dev_priv->vbios.execute)
+               return 0;
+
+       nv_mask(dev, reg + 0, mask, ctrl);
+       nv_wr32(dev, reg + 4, coef);
        return 0;
 }
 
index 7226f41..7cc37e6 100644 (file)
@@ -148,7 +148,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type)
 
        if (dev_priv->card_type == NV_10 &&
            nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) &&
-           nvbo->bo.mem.num_pages < vram_pages / 2) {
+           nvbo->bo.mem.num_pages < vram_pages / 4) {
                /*
                 * Make sure that the color and depth buffers are handled
                 * by independent memory controller units. Up to a 9x
index a319d56..bb6ec9e 100644 (file)
@@ -158,6 +158,7 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret,
        INIT_LIST_HEAD(&chan->nvsw.vbl_wait);
        INIT_LIST_HEAD(&chan->nvsw.flip);
        INIT_LIST_HEAD(&chan->fence.pending);
+       spin_lock_init(&chan->fence.lock);
 
        /* setup channel's memory and vm */
        ret = nouveau_gpuobj_channel_init(chan, vram_handle, gart_handle);
index e0d275e..cea6696 100644 (file)
@@ -710,7 +710,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
        case OUTPUT_DP:
                max_clock  = nv_encoder->dp.link_nr;
                max_clock *= nv_encoder->dp.link_bw;
-               clock = clock * nouveau_connector_bpp(connector) / 8;
+               clock = clock * nouveau_connector_bpp(connector) / 10;
                break;
        default:
                BUG_ON(1);
index 14a8627..3a4cc32 100644 (file)
@@ -487,6 +487,7 @@ int nouveau_fbcon_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
        struct nouveau_fbdev *nfbdev;
+       int preferred_bpp;
        int ret;
 
        nfbdev = kzalloc(sizeof(struct nouveau_fbdev), GFP_KERNEL);
@@ -505,7 +506,15 @@ int nouveau_fbcon_init(struct drm_device *dev)
        }
 
        drm_fb_helper_single_add_all_connectors(&nfbdev->helper);
-       drm_fb_helper_initial_config(&nfbdev->helper, 32);
+
+       if (dev_priv->vram_size <= 32 * 1024 * 1024)
+               preferred_bpp = 8;
+       else if (dev_priv->vram_size <= 64 * 1024 * 1024)
+               preferred_bpp = 16;
+       else
+               preferred_bpp = 32;
+
+       drm_fb_helper_initial_config(&nfbdev->helper, preferred_bpp);
        return 0;
 }
 
index 81116cf..2f6daae 100644 (file)
@@ -539,8 +539,6 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
                        return ret;
        }
 
-       INIT_LIST_HEAD(&chan->fence.pending);
-       spin_lock_init(&chan->fence.lock);
        atomic_set(&chan->fence.last_sequence_irq, 0);
        return 0;
 }
index c6143df..d39b220 100644 (file)
@@ -333,7 +333,7 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what,
 
        NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
 
-       for (i = 0; info[i].addr; i++) {
+       for (i = 0; i2c && info[i].addr; i++) {
                if (nouveau_probe_i2c_addr(i2c, info[i].addr) &&
                    (!match || match(i2c, &info[i]))) {
                        NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
index 9f178aa..33d03fb 100644 (file)
@@ -239,7 +239,7 @@ nouveau_perf_init(struct drm_device *dev)
        if(version == 0x15) {
                memtimings->timing =
                                kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
-               if(!memtimings) {
+               if (!memtimings->timing) {
                        NV_WARN(dev,"Could not allocate memtiming table\n");
                        return;
                }
index 82478e0..d8831ab 100644 (file)
@@ -579,6 +579,14 @@ nouveau_card_init(struct drm_device *dev)
        if (ret)
                goto out_display_early;
 
+       /* workaround an odd issue on nvc1 by disabling the device's
+        * nosnoop capability.  hopefully won't cause issues until a
+        * better fix is found - assuming there is one...
+        */
+       if (dev_priv->chipset == 0xc1) {
+               nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
+       }
+
        nouveau_pm_init(dev);
 
        ret = engine->vram.init(dev);
@@ -1102,12 +1110,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
        dev_priv->noaccel = !!nouveau_noaccel;
        if (nouveau_noaccel == -1) {
                switch (dev_priv->chipset) {
-               case 0xc1: /* known broken */
-               case 0xc8: /* never tested */
+#if 0
+               case 0xXX: /* known broken */
                        NV_INFO(dev, "acceleration disabled by default, pass "
                                     "noaccel=0 to force enable\n");
                        dev_priv->noaccel = true;
                        break;
+#endif
                default:
                        dev_priv->noaccel = false;
                        break;
index bbc0b9c..e676b0d 100644 (file)
@@ -57,12 +57,14 @@ read_pll_2(struct drm_device *dev, u32 reg)
        int P = (ctrl & 0x00070000) >> 16;
        u32 ref = 27000, clk = 0;
 
-       if (ctrl & 0x80000000)
+       if ((ctrl & 0x80000000) && M1) {
                clk = ref * N1 / M1;
-
-       if (!(ctrl & 0x00000100)) {
-               if (ctrl & 0x40000000)
-                       clk = clk * N2 / M2;
+               if ((ctrl & 0x40000100) == 0x40000000) {
+                       if (M2)
+                               clk = clk * N2 / M2;
+                       else
+                               clk = 0;
+               }
        }
 
        return clk >> P;
@@ -177,6 +179,11 @@ nv40_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl)
        }
 
        /* memory clock */
+       if (!perflvl->memory) {
+               info->mpll_ctrl = 0x00000000;
+               goto out;
+       }
+
        ret = nv40_calc_pll(dev, 0x004020, &pll, perflvl->memory,
                            &N1, &M1, &N2, &M2, &log2P);
        if (ret < 0)
@@ -264,6 +271,9 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state)
        mdelay(5);
        nv_mask(dev, 0x00c040, 0x00000333, info->ctrl);
 
+       if (!info->mpll_ctrl)
+               goto resume;
+
        /* wait for vblank start on active crtcs, disable memory access */
        for (i = 0; i < 2; i++) {
                if (!(crtc_mask & (1 << i)))
index 8c979b3..ac601f7 100644 (file)
@@ -131,8 +131,8 @@ nv50_graph_init(struct drm_device *dev, int engine)
        NV_DEBUG(dev, "\n");
 
        /* master reset */
-       nv_mask(dev, 0x000200, 0x00200100, 0x00000000);
-       nv_mask(dev, 0x000200, 0x00200100, 0x00200100);
+       nv_mask(dev, 0x000200, 0x00201000, 0x00000000);
+       nv_mask(dev, 0x000200, 0x00201000, 0x00201000);
        nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
 
        /* reset/enable traps and interrupts */
index d05c2c3..4b46d69 100644 (file)
@@ -601,7 +601,7 @@ nv50_graph_construct_mmio(struct nouveau_grctx *ctx)
                                        gr_def(ctx, offset + 0x1c, 0x00880000);
                                        break;
                                case 0x86:
-                                       gr_def(ctx, offset + 0x1c, 0x008c0000);
+                                       gr_def(ctx, offset + 0x1c, 0x018c0000);
                                        break;
                                case 0x92:
                                case 0x96:
index 9da2383..2e45e57 100644 (file)
@@ -160,7 +160,7 @@ nv50_vram_rblock(struct drm_device *dev)
        colbits  =  (r4 & 0x0000f000) >> 12;
        rowbitsa = ((r4 & 0x000f0000) >> 16) + 8;
        rowbitsb = ((r4 & 0x00f00000) >> 20) + 8;
-       banks    = ((r4 & 0x01000000) ? 8 : 4);
+       banks    = 1 << (((r4 & 0x03000000) >> 24) + 2);
 
        rowsize = parts * banks * (1 << colbits) * 8;
        predicted = rowsize << rowbitsa;
index bbdbc51..a74e501 100644 (file)
@@ -157,8 +157,8 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
        struct nvc0_graph_priv *priv = nv_engine(chan->dev, NVOBJ_ENGINE_GR);
        struct nvc0_graph_chan *grch = chan->engctx[NVOBJ_ENGINE_GR];
        struct drm_device *dev = chan->dev;
+       struct drm_nouveau_private *dev_priv = dev->dev_private;
        int i = 0, gpc, tp, ret;
-       u32 magic;
 
        ret = nouveau_gpuobj_new(dev, chan, 0x2000, 256, NVOBJ_FLAG_VM,
                                 &grch->unk408004);
@@ -207,14 +207,37 @@ nvc0_graph_create_context_mmio_list(struct nouveau_channel *chan)
        nv_wo32(grch->mmio, i++ * 4, 0x0041880c);
        nv_wo32(grch->mmio, i++ * 4, 0x80000018);
 
-       magic = 0x02180000;
-       nv_wo32(grch->mmio, i++ * 4, 0x00405830);
-       nv_wo32(grch->mmio, i++ * 4, magic);
-       for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
-               for (tp = 0; tp < priv->tp_nr[gpc]; tp++, magic += 0x0324) {
-                       u32 reg = 0x504520 + (gpc * 0x8000) + (tp * 0x0800);
-                       nv_wo32(grch->mmio, i++ * 4, reg);
-                       nv_wo32(grch->mmio, i++ * 4, magic);
+       if (dev_priv->chipset != 0xc1) {
+               u32 magic = 0x02180000;
+               nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+               nv_wo32(grch->mmio, i++ * 4, magic);
+               for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+                       for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+                               u32 reg = TP_UNIT(gpc, tp, 0x520);
+                               nv_wo32(grch->mmio, i++ * 4, reg);
+                               nv_wo32(grch->mmio, i++ * 4, magic);
+                               magic += 0x0324;
+                       }
+               }
+       } else {
+               u32 magic = 0x02180000;
+               nv_wo32(grch->mmio, i++ * 4, 0x00405830);
+               nv_wo32(grch->mmio, i++ * 4, magic | 0x0000218);
+               nv_wo32(grch->mmio, i++ * 4, 0x004064c4);
+               nv_wo32(grch->mmio, i++ * 4, 0x0086ffff);
+               for (gpc = 0; gpc < priv->gpc_nr; gpc++) {
+                       for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+                               u32 reg = TP_UNIT(gpc, tp, 0x520);
+                               nv_wo32(grch->mmio, i++ * 4, reg);
+                               nv_wo32(grch->mmio, i++ * 4, (1 << 28) | magic);
+                               magic += 0x0324;
+                       }
+                       for (tp = 0; tp < priv->tp_nr[gpc]; tp++) {
+                               u32 reg = TP_UNIT(gpc, tp, 0x544);
+                               nv_wo32(grch->mmio, i++ * 4, reg);
+                               nv_wo32(grch->mmio, i++ * 4, magic);
+                               magic += 0x0324;
+                       }
                }
        }
 
index dd0e6a7..96b0b93 100644 (file)
@@ -1812,6 +1812,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
                /* calculate first set of magics */
                memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
 
+               gpc = -1;
                for (tp = 0; tp < priv->tp_total; tp++) {
                        do {
                                gpc = (gpc + 1) % priv->gpc_nr;
@@ -1861,30 +1862,26 @@ nvc0_grctx_generate(struct nouveau_channel *chan)
 
        if (1) {
                u32 tp_mask = 0, tp_set = 0;
-               u8  tpnr[GPC_MAX];
+               u8  tpnr[GPC_MAX], a, b;
 
                memcpy(tpnr, priv->tp_nr, sizeof(priv->tp_nr));
                for (gpc = 0; gpc < priv->gpc_nr; gpc++)
                        tp_mask |= ((1 << priv->tp_nr[gpc]) - 1) << (gpc * 8);
 
-               gpc = -1;
-               for (i = 0, gpc = -1; i < 32; i++) {
-                       int ltp = i * (priv->tp_total - 1) / 32;
-
-                       do {
-                               gpc = (gpc + 1) % priv->gpc_nr;
-                       } while (!tpnr[gpc]);
-                       tp = priv->tp_nr[gpc] - tpnr[gpc]--;
+               for (i = 0, gpc = -1, b = -1; i < 32; i++) {
+                       a = (i * (priv->tp_total - 1)) / 32;
+                       if (a != b) {
+                               b = a;
+                               do {
+                                       gpc = (gpc + 1) % priv->gpc_nr;
+                               } while (!tpnr[gpc]);
+                               tp = priv->tp_nr[gpc] - tpnr[gpc]--;
 
-                       tp_set |= 1 << ((gpc * 8) + tp);
+                               tp_set |= 1 << ((gpc * 8) + tp);
+                       }
 
-                       do {
-                               nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
-                               tp_set ^= tp_mask;
-                               nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set);
-                               tp_set ^= tp_mask;
-                       } while (ltp == (++i * (priv->tp_total - 1) / 32));
-                       i--;
+                       nv_wr32(dev, 0x406800 + (i * 0x20), tp_set);
+                       nv_wr32(dev, 0x406c00 + (i * 0x20), tp_set ^ tp_mask);
                }
        }
 
index edbfe93..ce984d5 100644 (file)
@@ -43,7 +43,7 @@ static const u8 types[256] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
-       3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
+       3, 3, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
        3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
        3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
        3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
@@ -110,22 +110,26 @@ nvc0_vram_init(struct drm_device *dev)
        u32 bsize = nv_rd32(dev, 0x10f20c);
        u32 offset, length;
        bool uniform = true;
-       int ret, i;
+       int ret, part;
 
        NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
        NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize);
 
        /* read amount of vram attached to each memory controller */
-       for (i = 0; i < parts; i++) {
-               u32 psize = nv_rd32(dev, 0x11020c + (i * 0x1000));
+       part = 0;
+       while (parts) {
+               u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000));
+               if (psize == 0)
+                       continue;
+               parts--;
+
                if (psize != bsize) {
                        if (psize < bsize)
                                bsize = psize;
                        uniform = false;
                }
 
-               NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", i, psize);
-
+               NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize);
                dev_priv->vram_size += (u64)psize << 20;
        }
 
index 87921c8..87631fe 100644 (file)
@@ -1522,12 +1522,6 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc,
                                     struct drm_display_mode *mode,
                                     struct drm_display_mode *adjusted_mode)
 {
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
-
-       /* adjust pm to upcoming mode change */
-       radeon_pm_compute_clocks(rdev);
-
        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
                return false;
        return true;
index a0de485..6fb335a 100644 (file)
@@ -283,7 +283,7 @@ int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                }
        }
 
-       DRM_ERROR("aux i2c too many retries, giving up\n");
+       DRM_DEBUG_KMS("aux i2c too many retries, giving up\n");
        return -EREMOTEIO;
 }
 
index e4c384b..1d603a3 100644 (file)
@@ -157,6 +157,57 @@ int sumo_get_temp(struct radeon_device *rdev)
        return actual_temp * 1000;
 }
 
+void sumo_pm_init_profile(struct radeon_device *rdev)
+{
+       int idx;
+
+       /* default */
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;
+
+       /* low,mid sh/mh */
+       if (rdev->flags & RADEON_IS_MOBILITY)
+               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+       else
+               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
+
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
+
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;
+
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;
+
+       /* high sh/mh */
+       idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx =
+               rdev->pm.power_state[idx].num_clock_modes - 1;
+
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
+       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx =
+               rdev->pm.power_state[idx].num_clock_modes - 1;
+}
+
 void evergreen_pm_misc(struct radeon_device *rdev)
 {
        int req_ps_idx = rdev->pm.requested_power_state_index;
@@ -1219,7 +1270,7 @@ void evergreen_mc_program(struct radeon_device *rdev)
                WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
                        rdev->mc.vram_end >> 12);
        }
-       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
+       WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
        if (rdev->flags & RADEON_IS_IGP) {
                tmp = RREG32(MC_FUS_VM_FB_OFFSET) & 0x000FFFFF;
                tmp |= ((rdev->mc.vram_end >> 20) & 0xF) << 24;
index 7fdfa8e..38e1bda 100644 (file)
@@ -480,21 +480,23 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                }
                break;
        case DB_Z_INFO:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
-               if (r) {
-                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
-                                       "0x%04X\n", reg);
-                       return -EINVAL;
-               }
                track->db_z_info = radeon_get_ib_value(p, idx);
-               ib[idx] &= ~Z_ARRAY_MODE(0xf);
-               track->db_z_info &= ~Z_ARRAY_MODE(0xf);
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-                       ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-                       track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-               } else {
-                       ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-                       track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               if (!p->keep_tiling_flags) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                               "0x%04X\n", reg);
+                               return -EINVAL;
+                       }
+                       ib[idx] &= ~Z_ARRAY_MODE(0xf);
+                       track->db_z_info &= ~Z_ARRAY_MODE(0xf);
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                               ib[idx] |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                               track->db_z_info |= Z_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       } else {
+                               ib[idx] |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               track->db_z_info |= Z_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       }
                }
                break;
        case DB_STENCIL_INFO:
@@ -607,40 +609,44 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case CB_COLOR5_INFO:
        case CB_COLOR6_INFO:
        case CB_COLOR7_INFO:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
-               if (r) {
-                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
-                                       "0x%04X\n", reg);
-                       return -EINVAL;
-               }
                tmp = (reg - CB_COLOR0_INFO) / 0x3c;
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-                       ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-               } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-                       ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               if (!p->keep_tiling_flags) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                               "0x%04X\n", reg);
+                               return -EINVAL;
+                       }
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                               ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                               track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                               ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       }
                }
                break;
        case CB_COLOR8_INFO:
        case CB_COLOR9_INFO:
        case CB_COLOR10_INFO:
        case CB_COLOR11_INFO:
-               r = evergreen_cs_packet_next_reloc(p, &reloc);
-               if (r) {
-                       dev_warn(p->dev, "bad SET_CONTEXT_REG "
-                                       "0x%04X\n", reg);
-                       return -EINVAL;
-               }
                tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8;
                track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
-                       ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-               } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
-                       ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
-                       track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+               if (!p->keep_tiling_flags) {
+                       r = evergreen_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               dev_warn(p->dev, "bad SET_CONTEXT_REG "
+                                               "0x%04X\n", reg);
+                               return -EINVAL;
+                       }
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) {
+                               ib[idx] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                               track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                       } else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
+                               ib[idx] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               track->cb_color_info[tmp] |= CB_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                       }
                }
                break;
        case CB_COLOR0_PITCH:
@@ -1311,10 +1317,12 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
                                        return -EINVAL;
                                }
                                ib[idx+1+(i*8)+2] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-                               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-                                       ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
-                               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-                                       ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               if (!p->keep_tiling_flags) {
+                                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                                               ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_2D_TILED_THIN1);
+                                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                                               ib[idx+1+(i*8)+1] |= TEX_ARRAY_MODE(ARRAY_1D_TILED_THIN1);
+                               }
                                texture = reloc->robj;
                                /* tex mip base */
                                r = evergreen_cs_packet_next_reloc(p, &reloc);
index 400b26d..c93bc64 100644 (file)
@@ -701,16 +701,21 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                        return r;
                }
 
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-                       tile_flags |= R300_TXO_MACRO_TILE;
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-                       tile_flags |= R300_TXO_MICRO_TILE;
-               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-                       tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
-
-               tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
-               tmp |= tile_flags;
-               ib[idx] = tmp;
+               if (p->keep_tiling_flags) {
+                       ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */
+                                 ((idx_value & ~31) + (u32)reloc->lobj.gpu_offset);
+               } else {
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                               tile_flags |= R300_TXO_MACRO_TILE;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                               tile_flags |= R300_TXO_MICRO_TILE;
+                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+                               tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
+
+                       tmp = idx_value + ((u32)reloc->lobj.gpu_offset);
+                       tmp |= tile_flags;
+                       ib[idx] = tmp;
+               }
                track->textures[i].robj = reloc->robj;
                track->tex_dirty = true;
                break;
@@ -760,24 +765,26 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                /* RB3D_COLORPITCH1 */
                /* RB3D_COLORPITCH2 */
                /* RB3D_COLORPITCH3 */
-               r = r100_cs_packet_next_reloc(p, &reloc);
-               if (r) {
-                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
-                                 idx, reg);
-                       r100_cs_dump_packet(p, pkt);
-                       return r;
-               }
+               if (!p->keep_tiling_flags) {
+                       r = r100_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                         idx, reg);
+                               r100_cs_dump_packet(p, pkt);
+                               return r;
+                       }
 
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-                       tile_flags |= R300_COLOR_TILE_ENABLE;
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-                       tile_flags |= R300_COLOR_MICROTILE_ENABLE;
-               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-                       tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                               tile_flags |= R300_COLOR_TILE_ENABLE;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                               tile_flags |= R300_COLOR_MICROTILE_ENABLE;
+                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+                               tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
 
-               tmp = idx_value & ~(0x7 << 16);
-               tmp |= tile_flags;
-               ib[idx] = tmp;
+                       tmp = idx_value & ~(0x7 << 16);
+                       tmp |= tile_flags;
+                       ib[idx] = tmp;
+               }
                i = (reg - 0x4E38) >> 2;
                track->cb[i].pitch = idx_value & 0x3FFE;
                switch (((idx_value >> 21) & 0xF)) {
@@ -843,25 +850,26 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
                break;
        case 0x4F24:
                /* ZB_DEPTHPITCH */
-               r = r100_cs_packet_next_reloc(p, &reloc);
-               if (r) {
-                       DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
-                                 idx, reg);
-                       r100_cs_dump_packet(p, pkt);
-                       return r;
-               }
-
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-                       tile_flags |= R300_DEPTHMACROTILE_ENABLE;
-               if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-                       tile_flags |= R300_DEPTHMICROTILE_TILED;
-               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
-                       tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
+               if (!p->keep_tiling_flags) {
+                       r = r100_cs_packet_next_reloc(p, &reloc);
+                       if (r) {
+                               DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
+                                         idx, reg);
+                               r100_cs_dump_packet(p, pkt);
+                               return r;
+                       }
 
-               tmp = idx_value & ~(0x7 << 16);
-               tmp |= tile_flags;
-               ib[idx] = tmp;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                               tile_flags |= R300_DEPTHMACROTILE_ENABLE;
+                       if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                               tile_flags |= R300_DEPTHMICROTILE_TILED;
+                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO_SQUARE)
+                               tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
 
+                       tmp = idx_value & ~(0x7 << 16);
+                       tmp |= tile_flags;
+                       ib[idx] = tmp;
+               }
                track->zb.pitch = idx_value & 0x3FFC;
                track->zb_dirty = true;
                break;
index 19afc43..9cdda0b 100644 (file)
@@ -288,24 +288,6 @@ void r600_pm_get_dynpm_state(struct radeon_device *rdev)
                  pcie_lanes);
 }
 
-static int r600_pm_get_type_index(struct radeon_device *rdev,
-                                 enum radeon_pm_state_type ps_type,
-                                 int instance)
-{
-       int i;
-       int found_instance = -1;
-
-       for (i = 0; i < rdev->pm.num_power_states; i++) {
-               if (rdev->pm.power_state[i].type == ps_type) {
-                       found_instance++;
-                       if (found_instance == instance)
-                               return i;
-               }
-       }
-       /* return default if no match */
-       return rdev->pm.default_power_state_index;
-}
-
 void rs780_pm_init_profile(struct radeon_device *rdev)
 {
        if (rdev->pm.num_power_states == 2) {
@@ -421,6 +403,8 @@ void rs780_pm_init_profile(struct radeon_device *rdev)
 
 void r600_pm_init_profile(struct radeon_device *rdev)
 {
+       int idx;
+
        if (rdev->family == CHIP_R600) {
                /* XXX */
                /* default */
@@ -502,81 +486,43 @@ void r600_pm_init_profile(struct radeon_device *rdev)
                        rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
                        rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
                        /* low sh */
-                       if (rdev->flags & RADEON_IS_MOBILITY) {
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
-                       } else {
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
-                       }
+                       if (rdev->flags & RADEON_IS_MOBILITY)
+                               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
+                       else
+                               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
                        /* mid sh */
-                       if (rdev->flags & RADEON_IS_MOBILITY) {
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
-                       } else {
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
-                       }
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
                        /* high sh */
-                       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx =
-                               r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
-                       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx =
-                               r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+                       idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
+                       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
                        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
                        rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
                        /* low mh */
-                       if (rdev->flags & RADEON_IS_MOBILITY) {
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
-                       } else {
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
-                       }
+                       if (rdev->flags & RADEON_IS_MOBILITY)
+                               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
+                       else
+                               idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
                        /* mid mh */
-                       if (rdev->flags & RADEON_IS_MOBILITY) {
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1);
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
-                       } else {
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx =
-                                       r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
-                               rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
-                       }
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
+                       rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
                        /* high mh */
-                       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx =
-                               r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
-                       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx =
-                               r600_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+                       idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1);
+                       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
+                       rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
                        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
                        rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
                }
index 0a2e023..cb1acff 100644 (file)
@@ -941,7 +941,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->db_depth_control = radeon_get_ib_value(p, idx);
                break;
        case R_028010_DB_DEPTH_INFO:
-               if (r600_cs_packet_next_is_pkt3_nop(p)) {
+               if (!p->keep_tiling_flags &&
+                   r600_cs_packet_next_is_pkt3_nop(p)) {
                        r = r600_cs_packet_next_reloc(p, &reloc);
                        if (r) {
                                dev_warn(p->dev, "bad SET_CONTEXT_REG "
@@ -992,7 +993,8 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_0280B4_CB_COLOR5_INFO:
        case R_0280B8_CB_COLOR6_INFO:
        case R_0280BC_CB_COLOR7_INFO:
-               if (r600_cs_packet_next_is_pkt3_nop(p)) {
+               if (!p->keep_tiling_flags &&
+                    r600_cs_packet_next_is_pkt3_nop(p)) {
                        r = r600_cs_packet_next_reloc(p, &reloc);
                        if (r) {
                                dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
@@ -1291,10 +1293,12 @@ static int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
        mip_offset <<= 8;
 
        word0 = radeon_get_ib_value(p, idx + 0);
-       if (tiling_flags & RADEON_TILING_MACRO)
-               word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
-       else if (tiling_flags & RADEON_TILING_MICRO)
-               word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+       if (!p->keep_tiling_flags) {
+               if (tiling_flags & RADEON_TILING_MACRO)
+                       word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
+               else if (tiling_flags & RADEON_TILING_MICRO)
+                       word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+       }
        word1 = radeon_get_ib_value(p, idx + 1);
        w0 = G_038000_TEX_WIDTH(word0) + 1;
        h0 = G_038004_TEX_HEIGHT(word1) + 1;
@@ -1621,10 +1625,12 @@ static int r600_packet3_check(struct radeon_cs_parser *p,
                                        return -EINVAL;
                                }
                                base_offset = (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
-                               if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
-                                       ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
-                               else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
-                                       ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+                               if (!p->keep_tiling_flags) {
+                                       if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
+                                               ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
+                                       else if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
+                                               ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
+                               }
                                texture = reloc->robj;
                                /* tex mip base */
                                r = r600_cs_packet_next_reloc(p, &reloc);
index b316b30..8227e76 100644 (file)
@@ -611,7 +611,8 @@ struct radeon_cs_parser {
        struct radeon_ib        *ib;
        void                    *track;
        unsigned                family;
-       int parser_error;
+       int                     parser_error;
+       bool                    keep_tiling_flags;
 };
 
 extern int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx);
@@ -784,8 +785,7 @@ struct radeon_pm_clock_info {
 
 struct radeon_power_state {
        enum radeon_pm_state_type type;
-       /* XXX: use a define for num clock modes */
-       struct radeon_pm_clock_info clock_info[8];
+       struct radeon_pm_clock_info *clock_info;
        /* number of valid clock modes in this power state */
        int num_clock_modes;
        struct radeon_pm_clock_info *default_clock_mode;
@@ -855,6 +855,9 @@ struct radeon_pm {
        struct device           *int_hwmon_dev;
 };
 
+int radeon_pm_get_type_index(struct radeon_device *rdev,
+                            enum radeon_pm_state_type ps_type,
+                            int instance);
 
 /*
  * Benchmarking
@@ -1142,6 +1145,48 @@ struct r600_vram_scratch {
        u64                             gpu_addr;
 };
 
+
+/*
+ * Mutex which allows recursive locking from the same process.
+ */
+struct radeon_mutex {
+       struct mutex            mutex;
+       struct task_struct      *owner;
+       int                     level;
+};
+
+static inline void radeon_mutex_init(struct radeon_mutex *mutex)
+{
+       mutex_init(&mutex->mutex);
+       mutex->owner = NULL;
+       mutex->level = 0;
+}
+
+static inline void radeon_mutex_lock(struct radeon_mutex *mutex)
+{
+       if (mutex_trylock(&mutex->mutex)) {
+               /* The mutex was unlocked before, so it's ours now */
+               mutex->owner = current;
+       } else if (mutex->owner != current) {
+               /* Another process locked the mutex, take it */
+               mutex_lock(&mutex->mutex);
+               mutex->owner = current;
+       }
+       /* Otherwise the mutex was already locked by this process */
+
+       mutex->level++;
+}
+
+static inline void radeon_mutex_unlock(struct radeon_mutex *mutex)
+{
+       if (--mutex->level > 0)
+               return;
+
+       mutex->owner = NULL;
+       mutex_unlock(&mutex->mutex);
+}
+
+
 /*
  * Core structure, functions and helpers.
  */
@@ -1197,7 +1242,7 @@ struct radeon_device {
        struct radeon_gem               gem;
        struct radeon_pm                pm;
        uint32_t                        bios_scratch[RADEON_BIOS_NUM_SCRATCH];
-       struct mutex                    cs_mutex;
+       struct radeon_mutex             cs_mutex;
        struct radeon_wb                wb;
        struct radeon_dummy_page        dummy_page;
        bool                            gpu_lockup;
index e294456..a2e1eae 100644 (file)
@@ -834,7 +834,7 @@ static struct radeon_asic sumo_asic = {
        .pm_misc = &evergreen_pm_misc,
        .pm_prepare = &evergreen_pm_prepare,
        .pm_finish = &evergreen_pm_finish,
-       .pm_init_profile = &rs780_pm_init_profile,
+       .pm_init_profile = &sumo_pm_init_profile,
        .pm_get_dynpm_state = &r600_pm_get_dynpm_state,
        .pre_page_flip = &evergreen_pre_page_flip,
        .page_flip = &evergreen_page_flip,
index 85f14f0..5991484 100644 (file)
@@ -413,6 +413,7 @@ extern int evergreen_cs_parse(struct radeon_cs_parser *p);
 extern void evergreen_pm_misc(struct radeon_device *rdev);
 extern void evergreen_pm_prepare(struct radeon_device *rdev);
 extern void evergreen_pm_finish(struct radeon_device *rdev);
+extern void sumo_pm_init_profile(struct radeon_device *rdev);
 extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc);
 extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);
index 08d0b94..d24baf3 100644 (file)
@@ -62,6 +62,87 @@ union atom_supported_devices {
        struct _ATOM_SUPPORTED_DEVICES_INFO_2d1 info_2d1;
 };
 
+static void radeon_lookup_i2c_gpio_quirks(struct radeon_device *rdev,
+                                         ATOM_GPIO_I2C_ASSIGMENT *gpio,
+                                         u8 index)
+{
+       /* r4xx mask is technically not used by the hw, so patch in the legacy mask bits */
+       if ((rdev->family == CHIP_R420) ||
+           (rdev->family == CHIP_R423) ||
+           (rdev->family == CHIP_RV410)) {
+               if ((le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0018) ||
+                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x0019) ||
+                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x001a)) {
+                       gpio->ucClkMaskShift = 0x19;
+                       gpio->ucDataMaskShift = 0x18;
+               }
+       }
+
+       /* some evergreen boards have bad data for this entry */
+       if (ASIC_IS_DCE4(rdev)) {
+               if ((index == 7) &&
+                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
+                   (gpio->sucI2cId.ucAccess == 0)) {
+                       gpio->sucI2cId.ucAccess = 0x97;
+                       gpio->ucDataMaskShift = 8;
+                       gpio->ucDataEnShift = 8;
+                       gpio->ucDataY_Shift = 8;
+                       gpio->ucDataA_Shift = 8;
+               }
+       }
+
+       /* some DCE3 boards have bad data for this entry */
+       if (ASIC_IS_DCE3(rdev)) {
+               if ((index == 4) &&
+                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
+                   (gpio->sucI2cId.ucAccess == 0x94))
+                       gpio->sucI2cId.ucAccess = 0x14;
+       }
+}
+
+static struct radeon_i2c_bus_rec radeon_get_bus_rec_for_i2c_gpio(ATOM_GPIO_I2C_ASSIGMENT *gpio)
+{
+       struct radeon_i2c_bus_rec i2c;
+
+       memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
+
+       i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
+       i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
+       i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
+       i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
+       i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
+       i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
+       i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
+       i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
+       i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
+       i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
+       i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
+       i2c.en_data_mask = (1 << gpio->ucDataEnShift);
+       i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
+       i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
+       i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
+       i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
+
+       if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
+               i2c.hw_capable = true;
+       else
+               i2c.hw_capable = false;
+
+       if (gpio->sucI2cId.ucAccess == 0xa0)
+               i2c.mm_i2c = true;
+       else
+               i2c.mm_i2c = false;
+
+       i2c.i2c_id = gpio->sucI2cId.ucAccess;
+
+       if (i2c.mask_clk_reg)
+               i2c.valid = true;
+       else
+               i2c.valid = false;
+
+       return i2c;
+}
+
 static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rdev,
                                                               uint8_t id)
 {
@@ -85,59 +166,10 @@ static struct radeon_i2c_bus_rec radeon_lookup_i2c_gpio(struct radeon_device *rd
                for (i = 0; i < num_indices; i++) {
                        gpio = &i2c_info->asGPIO_Info[i];
 
-                       /* some evergreen boards have bad data for this entry */
-                       if (ASIC_IS_DCE4(rdev)) {
-                               if ((i == 7) &&
-                                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
-                                   (gpio->sucI2cId.ucAccess == 0)) {
-                                       gpio->sucI2cId.ucAccess = 0x97;
-                                       gpio->ucDataMaskShift = 8;
-                                       gpio->ucDataEnShift = 8;
-                                       gpio->ucDataY_Shift = 8;
-                                       gpio->ucDataA_Shift = 8;
-                               }
-                       }
-
-                       /* some DCE3 boards have bad data for this entry */
-                       if (ASIC_IS_DCE3(rdev)) {
-                               if ((i == 4) &&
-                                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
-                                   (gpio->sucI2cId.ucAccess == 0x94))
-                                       gpio->sucI2cId.ucAccess = 0x14;
-                       }
+                       radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
 
                        if (gpio->sucI2cId.ucAccess == id) {
-                               i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-                               i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-                               i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-                               i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-                               i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-                               i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-                               i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-                               i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-                               i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-                               i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-                               i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-                               i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-                               i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-                               i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-                               i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-                               i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
-
-                               if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-                                       i2c.hw_capable = true;
-                               else
-                                       i2c.hw_capable = false;
-
-                               if (gpio->sucI2cId.ucAccess == 0xa0)
-                                       i2c.mm_i2c = true;
-                               else
-                                       i2c.mm_i2c = false;
-
-                               i2c.i2c_id = gpio->sucI2cId.ucAccess;
-
-                               if (i2c.mask_clk_reg)
-                                       i2c.valid = true;
+                               i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
                                break;
                        }
                }
@@ -157,8 +189,6 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
        int i, num_indices;
        char stmp[32];
 
-       memset(&i2c, 0, sizeof(struct radeon_i2c_bus_rec));
-
        if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) {
                i2c_info = (struct _ATOM_GPIO_I2C_INFO *)(ctx->bios + data_offset);
 
@@ -167,60 +197,12 @@ void radeon_atombios_i2c_init(struct radeon_device *rdev)
 
                for (i = 0; i < num_indices; i++) {
                        gpio = &i2c_info->asGPIO_Info[i];
-                       i2c.valid = false;
-
-                       /* some evergreen boards have bad data for this entry */
-                       if (ASIC_IS_DCE4(rdev)) {
-                               if ((i == 7) &&
-                                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1936) &&
-                                   (gpio->sucI2cId.ucAccess == 0)) {
-                                       gpio->sucI2cId.ucAccess = 0x97;
-                                       gpio->ucDataMaskShift = 8;
-                                       gpio->ucDataEnShift = 8;
-                                       gpio->ucDataY_Shift = 8;
-                                       gpio->ucDataA_Shift = 8;
-                               }
-                       }
 
-                       /* some DCE3 boards have bad data for this entry */
-                       if (ASIC_IS_DCE3(rdev)) {
-                               if ((i == 4) &&
-                                   (le16_to_cpu(gpio->usClkMaskRegisterIndex) == 0x1fda) &&
-                                   (gpio->sucI2cId.ucAccess == 0x94))
-                                       gpio->sucI2cId.ucAccess = 0x14;
-                       }
+                       radeon_lookup_i2c_gpio_quirks(rdev, gpio, i);
 
-                       i2c.mask_clk_reg = le16_to_cpu(gpio->usClkMaskRegisterIndex) * 4;
-                       i2c.mask_data_reg = le16_to_cpu(gpio->usDataMaskRegisterIndex) * 4;
-                       i2c.en_clk_reg = le16_to_cpu(gpio->usClkEnRegisterIndex) * 4;
-                       i2c.en_data_reg = le16_to_cpu(gpio->usDataEnRegisterIndex) * 4;
-                       i2c.y_clk_reg = le16_to_cpu(gpio->usClkY_RegisterIndex) * 4;
-                       i2c.y_data_reg = le16_to_cpu(gpio->usDataY_RegisterIndex) * 4;
-                       i2c.a_clk_reg = le16_to_cpu(gpio->usClkA_RegisterIndex) * 4;
-                       i2c.a_data_reg = le16_to_cpu(gpio->usDataA_RegisterIndex) * 4;
-                       i2c.mask_clk_mask = (1 << gpio->ucClkMaskShift);
-                       i2c.mask_data_mask = (1 << gpio->ucDataMaskShift);
-                       i2c.en_clk_mask = (1 << gpio->ucClkEnShift);
-                       i2c.en_data_mask = (1 << gpio->ucDataEnShift);
-                       i2c.y_clk_mask = (1 << gpio->ucClkY_Shift);
-                       i2c.y_data_mask = (1 << gpio->ucDataY_Shift);
-                       i2c.a_clk_mask = (1 << gpio->ucClkA_Shift);
-                       i2c.a_data_mask = (1 << gpio->ucDataA_Shift);
-
-                       if (gpio->sucI2cId.sbfAccess.bfHW_Capable)
-                               i2c.hw_capable = true;
-                       else
-                               i2c.hw_capable = false;
-
-                       if (gpio->sucI2cId.ucAccess == 0xa0)
-                               i2c.mm_i2c = true;
-                       else
-                               i2c.mm_i2c = false;
+                       i2c = radeon_get_bus_rec_for_i2c_gpio(gpio);
 
-                       i2c.i2c_id = gpio->sucI2cId.ucAccess;
-
-                       if (i2c.mask_clk_reg) {
-                               i2c.valid = true;
+                       if (i2c.valid) {
                                sprintf(stmp, "0x%x", i2c.i2c_id);
                                rdev->i2c_bus[i] = radeon_i2c_create(rdev->ddev, &i2c, stmp);
                        }
@@ -1996,10 +1978,14 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
                return state_index;
        /* last mode is usually default, array is low to high */
        for (i = 0; i < num_modes; i++) {
+               rdev->pm.power_state[state_index].clock_info =
+                       kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+               if (!rdev->pm.power_state[state_index].clock_info)
+                       return state_index;
+               rdev->pm.power_state[state_index].num_clock_modes = 1;
                rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
                switch (frev) {
                case 1:
-                       rdev->pm.power_state[state_index].num_clock_modes = 1;
                        rdev->pm.power_state[state_index].clock_info[0].mclk =
                                le16_to_cpu(power_info->info.asPowerPlayInfo[i].usMemoryClock);
                        rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2035,7 +2021,6 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
                        state_index++;
                        break;
                case 2:
-                       rdev->pm.power_state[state_index].num_clock_modes = 1;
                        rdev->pm.power_state[state_index].clock_info[0].mclk =
                                le32_to_cpu(power_info->info_2.asPowerPlayInfo[i].ulMemoryClock);
                        rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2072,7 +2057,6 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev)
                        state_index++;
                        break;
                case 3:
-                       rdev->pm.power_state[state_index].num_clock_modes = 1;
                        rdev->pm.power_state[state_index].clock_info[0].mclk =
                                le32_to_cpu(power_info->info_3.asPowerPlayInfo[i].ulMemoryClock);
                        rdev->pm.power_state[state_index].clock_info[0].sclk =
@@ -2257,7 +2241,7 @@ static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rde
                rdev->pm.default_power_state_index = state_index;
                rdev->pm.power_state[state_index].default_clock_mode =
                        &rdev->pm.power_state[state_index].clock_info[mode_index - 1];
-               if (ASIC_IS_DCE5(rdev)) {
+               if (ASIC_IS_DCE5(rdev) && !(rdev->flags & RADEON_IS_IGP)) {
                        /* NI chips post without MC ucode, so default clocks are strobe mode only */
                        rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
                        rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
@@ -2377,17 +2361,31 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev)
                         le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset) +
                         (power_state->v1.ucNonClockStateIndex *
                          power_info->pplib.ucNonClockSize));
-               for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
-                       clock_info = (union pplib_clock_info *)
-                               (mode_info->atom_context->bios + data_offset +
-                                le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
-                                (power_state->v1.ucClockStateIndices[j] *
-                                 power_info->pplib.ucClockInfoSize));
-                       valid = radeon_atombios_parse_pplib_clock_info(rdev,
-                                                                      state_index, mode_index,
-                                                                      clock_info);
-                       if (valid)
-                               mode_index++;
+               rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
+                                                            ((power_info->pplib.ucStateEntrySize - 1) ?
+                                                             (power_info->pplib.ucStateEntrySize - 1) : 1),
+                                                            GFP_KERNEL);
+               if (!rdev->pm.power_state[i].clock_info)
+                       return state_index;
+               if (power_info->pplib.ucStateEntrySize - 1) {
+                       for (j = 0; j < (power_info->pplib.ucStateEntrySize - 1); j++) {
+                               clock_info = (union pplib_clock_info *)
+                                       (mode_info->atom_context->bios + data_offset +
+                                        le16_to_cpu(power_info->pplib.usClockInfoArrayOffset) +
+                                        (power_state->v1.ucClockStateIndices[j] *
+                                         power_info->pplib.ucClockInfoSize));
+                               valid = radeon_atombios_parse_pplib_clock_info(rdev,
+                                                                              state_index, mode_index,
+                                                                              clock_info);
+                               if (valid)
+                                       mode_index++;
+                       }
+               } else {
+                       rdev->pm.power_state[state_index].clock_info[0].mclk =
+                               rdev->clock.default_mclk;
+                       rdev->pm.power_state[state_index].clock_info[0].sclk =
+                               rdev->clock.default_sclk;
+                       mode_index++;
                }
                rdev->pm.power_state[state_index].num_clock_modes = mode_index;
                if (mode_index) {
@@ -2456,18 +2454,32 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev)
                non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */
                non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *)
                        &non_clock_info_array->nonClockInfo[non_clock_array_index];
-               for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
-                       clock_array_index = power_state->v2.clockInfoIndex[j];
-                       /* XXX this might be an inagua bug... */
-                       if (clock_array_index >= clock_info_array->ucNumEntries)
-                               continue;
-                       clock_info = (union pplib_clock_info *)
-                               &clock_info_array->clockInfo[clock_array_index];
-                       valid = radeon_atombios_parse_pplib_clock_info(rdev,
-                                                                      state_index, mode_index,
-                                                                      clock_info);
-                       if (valid)
-                               mode_index++;
+               rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) *
+                                                            (power_state->v2.ucNumDPMLevels ?
+                                                             power_state->v2.ucNumDPMLevels : 1),
+                                                            GFP_KERNEL);
+               if (!rdev->pm.power_state[i].clock_info)
+                       return state_index;
+               if (power_state->v2.ucNumDPMLevels) {
+                       for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) {
+                               clock_array_index = power_state->v2.clockInfoIndex[j];
+                               /* XXX this might be an inagua bug... */
+                               if (clock_array_index >= clock_info_array->ucNumEntries)
+                                       continue;
+                               clock_info = (union pplib_clock_info *)
+                                       &clock_info_array->clockInfo[clock_array_index];
+                               valid = radeon_atombios_parse_pplib_clock_info(rdev,
+                                                                              state_index, mode_index,
+                                                                              clock_info);
+                               if (valid)
+                                       mode_index++;
+                       }
+               } else {
+                       rdev->pm.power_state[state_index].clock_info[0].mclk =
+                               rdev->clock.default_mclk;
+                       rdev->pm.power_state[state_index].clock_info[0].sclk =
+                               rdev->clock.default_sclk;
+                       mode_index++;
                }
                rdev->pm.power_state[state_index].num_clock_modes = mode_index;
                if (mode_index) {
@@ -2524,19 +2536,23 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
        } else {
                rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL);
                if (rdev->pm.power_state) {
-                       /* add the default mode */
-                       rdev->pm.power_state[state_index].type =
-                               POWER_STATE_TYPE_DEFAULT;
-                       rdev->pm.power_state[state_index].num_clock_modes = 1;
-                       rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
-                       rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
-                       rdev->pm.power_state[state_index].default_clock_mode =
-                               &rdev->pm.power_state[state_index].clock_info[0];
-                       rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
-                       rdev->pm.power_state[state_index].pcie_lanes = 16;
-                       rdev->pm.default_power_state_index = state_index;
-                       rdev->pm.power_state[state_index].flags = 0;
-                       state_index++;
+                       rdev->pm.power_state[0].clock_info =
+                               kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+                       if (rdev->pm.power_state[0].clock_info) {
+                               /* add the default mode */
+                               rdev->pm.power_state[state_index].type =
+                                       POWER_STATE_TYPE_DEFAULT;
+                               rdev->pm.power_state[state_index].num_clock_modes = 1;
+                               rdev->pm.power_state[state_index].clock_info[0].mclk = rdev->clock.default_mclk;
+                               rdev->pm.power_state[state_index].clock_info[0].sclk = rdev->clock.default_sclk;
+                               rdev->pm.power_state[state_index].default_clock_mode =
+                                       &rdev->pm.power_state[state_index].clock_info[0];
+                               rdev->pm.power_state[state_index].clock_info[0].voltage.type = VOLTAGE_NONE;
+                               rdev->pm.power_state[state_index].pcie_lanes = 16;
+                               rdev->pm.default_power_state_index = state_index;
+                               rdev->pm.power_state[state_index].flags = 0;
+                               state_index++;
+                       }
                }
        }
 
index 5cafc90..17e1a9b 100644 (file)
@@ -98,7 +98,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
        struct radeon_bo *sobj = NULL;
        uint64_t saddr, daddr;
        int r, n;
-       unsigned int time;
+       int time;
 
        n = RADEON_BENCHMARK_ITERATIONS;
        r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj);
index 8bf83c4..81fc100 100644 (file)
@@ -2563,14 +2563,17 @@ void radeon_combios_get_power_modes(struct radeon_device *rdev)
 
        /* allocate 2 power states */
        rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * 2, GFP_KERNEL);
-       if (!rdev->pm.power_state) {
-               rdev->pm.default_power_state_index = state_index;
-               rdev->pm.num_power_states = 0;
-
-               rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
-               rdev->pm.current_clock_mode_index = 0;
-               return;
-       }
+       if (rdev->pm.power_state) {
+               /* allocate 1 clock mode per state */
+               rdev->pm.power_state[0].clock_info =
+                       kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+               rdev->pm.power_state[1].clock_info =
+                       kzalloc(sizeof(struct radeon_pm_clock_info) * 1, GFP_KERNEL);
+               if (!rdev->pm.power_state[0].clock_info ||
+                   !rdev->pm.power_state[1].clock_info)
+                       goto pm_failed;
+       } else
+               goto pm_failed;
 
        /* check for a thermal chip */
        offset = combios_get_table_offset(dev, COMBIOS_OVERDRIVE_INFO_TABLE);
@@ -2733,6 +2736,14 @@ default_mode:
        rdev->pm.default_power_state_index = state_index;
        rdev->pm.num_power_states = state_index + 1;
 
+       rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
+       rdev->pm.current_clock_mode_index = 0;
+       return;
+
+pm_failed:
+       rdev->pm.default_power_state_index = state_index;
+       rdev->pm.num_power_states = 0;
+
        rdev->pm.current_power_state_index = rdev->pm.default_power_state_index;
        rdev->pm.current_clock_mode_index = 0;
 }
index fae00c0..29afd71 100644 (file)
@@ -93,7 +93,7 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
 {
        struct drm_radeon_cs *cs = data;
        uint64_t *chunk_array_ptr;
-       unsigned size, i;
+       unsigned size, i, flags = 0;
 
        if (!cs->num_chunks) {
                return 0;
@@ -140,6 +140,10 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                        if (p->chunks[i].length_dw == 0)
                                return -EINVAL;
                }
+               if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS &&
+                   !p->chunks[i].length_dw) {
+                       return -EINVAL;
+               }
 
                p->chunks[i].length_dw = user_chunk.length_dw;
                p->chunks[i].user_ptr = (void __user *)(unsigned long)user_chunk.chunk_data;
@@ -155,6 +159,9 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                                               p->chunks[i].user_ptr, size)) {
                                return -EFAULT;
                        }
+                       if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_FLAGS) {
+                               flags = p->chunks[i].kdata[0];
+                       }
                } else {
                        p->chunks[i].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
                        p->chunks[i].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
@@ -174,6 +181,8 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
                          p->chunks[p->chunk_ib_idx].length_dw);
                return -EINVAL;
        }
+
+       p->keep_tiling_flags = (flags & RADEON_CS_KEEP_TILING_FLAGS) != 0;
        return 0;
 }
 
@@ -222,7 +231,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        struct radeon_cs_chunk *ib_chunk;
        int r;
 
-       mutex_lock(&rdev->cs_mutex);
+       radeon_mutex_lock(&rdev->cs_mutex);
        /* initialize parser */
        memset(&parser, 0, sizeof(struct radeon_cs_parser));
        parser.filp = filp;
@@ -233,14 +242,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        if (r) {
                DRM_ERROR("Failed to initialize parser !\n");
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        r =  radeon_ib_get(rdev, &parser.ib);
        if (r) {
                DRM_ERROR("Failed to get ib !\n");
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        r = radeon_cs_parser_relocs(&parser);
@@ -248,7 +257,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                if (r != -ERESTARTSYS)
                        DRM_ERROR("Failed to parse relocation %d!\n", r);
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        /* Copy the packet into the IB, the parser will read from the
@@ -260,14 +269,14 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
        if (r || parser.parser_error) {
                DRM_ERROR("Invalid command stream !\n");
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        r = radeon_cs_finish_pages(&parser);
        if (r) {
                DRM_ERROR("Invalid command stream !\n");
                radeon_cs_parser_fini(&parser, r);
-               mutex_unlock(&rdev->cs_mutex);
+               radeon_mutex_unlock(&rdev->cs_mutex);
                return r;
        }
        r = radeon_ib_schedule(rdev, parser.ib);
@@ -275,7 +284,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                DRM_ERROR("Failed to schedule IB !\n");
        }
        radeon_cs_parser_fini(&parser, r);
-       mutex_unlock(&rdev->cs_mutex);
+       radeon_mutex_unlock(&rdev->cs_mutex);
        return r;
 }
 
index c33bc91..c4d00a1 100644 (file)
@@ -716,7 +716,7 @@ int radeon_device_init(struct radeon_device *rdev,
 
        /* mutex initialization are all done here so we
         * can recall function without having locking issues */
-       mutex_init(&rdev->cs_mutex);
+       radeon_mutex_init(&rdev->cs_mutex);
        mutex_init(&rdev->ib_pool.mutex);
        mutex_init(&rdev->cp.mutex);
        mutex_init(&rdev->dc_hw_i2c_mutex);
@@ -955,6 +955,9 @@ int radeon_gpu_reset(struct radeon_device *rdev)
        int r;
        int resched;
 
+       /* Prevent CS ioctl from interfering */
+       radeon_mutex_lock(&rdev->cs_mutex);
+
        radeon_save_bios_scratch_regs(rdev);
        /* block TTM */
        resched = ttm_bo_lock_delayed_workqueue(&rdev->mman.bdev);
@@ -967,10 +970,15 @@ int radeon_gpu_reset(struct radeon_device *rdev)
                radeon_restore_bios_scratch_regs(rdev);
                drm_helper_resume_force_mode(rdev->ddev);
                ttm_bo_unlock_delayed_workqueue(&rdev->mman.bdev, resched);
-               return 0;
        }
-       /* bad news, how to tell it to userspace ? */
-       dev_info(rdev->dev, "GPU reset failed\n");
+
+       radeon_mutex_unlock(&rdev->cs_mutex);
+
+       if (r) {
+               /* bad news, how to tell it to userspace ? */
+               dev_info(rdev->dev, "GPU reset failed\n");
+       }
+
        return r;
 }
 
index a0b35e9..71499fc 100644 (file)
  *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
  *   2.10.0 - fusion 2D tiling
  *   2.11.0 - backend map, initial compute support for the CS checker
+ *   2.12.0 - RADEON_CS_KEEP_TILING_FLAGS
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       11
+#define KMS_DRIVER_MINOR       12
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index 41a5d48..daadf21 100644 (file)
@@ -991,12 +991,6 @@ static bool radeon_crtc_mode_fixup(struct drm_crtc *crtc,
                                   struct drm_display_mode *mode,
                                   struct drm_display_mode *adjusted_mode)
 {
-       struct drm_device *dev = crtc->dev;
-       struct radeon_device *rdev = dev->dev_private;
-
-       /* adjust pm to upcoming mode change */
-       radeon_pm_compute_clocks(rdev);
-
        if (!radeon_crtc_scaling_mode_fixup(crtc, mode, adjusted_mode))
                return false;
        return true;
index 6fabe89..78a665b 100644 (file)
@@ -53,6 +53,24 @@ static void radeon_pm_set_clocks(struct radeon_device *rdev);
 
 #define ACPI_AC_CLASS           "ac_adapter"
 
+int radeon_pm_get_type_index(struct radeon_device *rdev,
+                            enum radeon_pm_state_type ps_type,
+                            int instance)
+{
+       int i;
+       int found_instance = -1;
+
+       for (i = 0; i < rdev->pm.num_power_states; i++) {
+               if (rdev->pm.power_state[i].type == ps_type) {
+                       found_instance++;
+                       if (found_instance == instance)
+                               return i;
+               }
+       }
+       /* return default if no match */
+       return rdev->pm.default_power_state_index;
+}
+
 #ifdef CONFIG_ACPI
 static int radeon_acpi_event(struct notifier_block *nb,
                             unsigned long val,
index 617b646..0bb0f5f 100644 (file)
@@ -574,10 +574,16 @@ retry:
                return ret;
 
        spin_lock(&glob->lru_lock);
+
+       if (unlikely(list_empty(&bo->ddestroy))) {
+               spin_unlock(&glob->lru_lock);
+               return 0;
+       }
+
        ret = ttm_bo_reserve_locked(bo, interruptible,
                                    no_wait_reserve, false, 0);
 
-       if (unlikely(ret != 0) || list_empty(&bo->ddestroy)) {
+       if (unlikely(ret != 0)) {
                spin_unlock(&glob->lru_lock);
                return ret;
        }
index 03daefa..880e285 100644 (file)
@@ -105,6 +105,10 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
        struct vmw_dma_buffer *dmabuf = NULL;
        int ret;
 
+       /* A lot of the code assumes this */
+       if (handle && (width != 64 || height != 64))
+               return -EINVAL;
+
        if (handle) {
                ret = vmw_user_surface_lookup_handle(dev_priv, tfile,
                                                     handle, &surface);
@@ -410,8 +414,9 @@ static int do_surface_dirty_sou(struct vmw_private *dev_priv,
        top = clips->y1;
        bottom = clips->y2;
 
-       clips_ptr = clips;
-       for (i = 1; i < num_clips; i++, clips_ptr += inc) {
+       /* skip the first clip rect */
+       for (i = 1, clips_ptr = clips + inc;
+            i < num_clips; i++, clips_ptr += inc) {
                left = min_t(int, left, (int)clips_ptr->x1);
                right = max_t(int, right, (int)clips_ptr->x2);
                top = min_t(int, top, (int)clips_ptr->y1);
@@ -1323,7 +1328,10 @@ int vmw_kms_close(struct vmw_private *dev_priv)
         * drm_encoder_cleanup which takes the lock we deadlock.
         */
        drm_mode_config_cleanup(dev_priv->dev);
-       vmw_kms_close_legacy_display_system(dev_priv);
+       if (dev_priv->sou_priv)
+               vmw_kms_close_screen_object_display(dev_priv);
+       else
+               vmw_kms_close_legacy_display_system(dev_priv);
        return 0;
 }
 
index c72f1c0..111d956 100644 (file)
@@ -465,31 +465,29 @@ static void vga_arbiter_check_bridge_sharing(struct vga_device *vgadev)
        while (new_bus) {
                new_bridge = new_bus->self;
 
-               if (new_bridge) {
-                       /* go through list of devices already registered */
-                       list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
-                               bus = same_bridge_vgadev->pdev->bus;
-                               bridge = bus->self;
-
-                               /* see if the share a bridge with this device */
-                               if (new_bridge == bridge) {
-                                       /* if their direct parent bridge is the same
-                                          as any bridge of this device then it can't be used
-                                          for that device */
-                                       same_bridge_vgadev->bridge_has_one_vga = false;
-                               }
+               /* go through list of devices already registered */
+               list_for_each_entry(same_bridge_vgadev, &vga_list, list) {
+                       bus = same_bridge_vgadev->pdev->bus;
+                       bridge = bus->self;
+
+                       /* see if the share a bridge with this device */
+                       if (new_bridge == bridge) {
+                               /* if their direct parent bridge is the same
+                                  as any bridge of this device then it can't be used
+                                  for that device */
+                               same_bridge_vgadev->bridge_has_one_vga = false;
+                       }
 
-                               /* now iterate the previous devices bridge hierarchy */
-                               /* if the new devices parent bridge is in the other devices
-                                  hierarchy then we can't use it to control this device */
-                               while (bus) {
-                                       bridge = bus->self;
-                                       if (bridge) {
-                                               if (bridge == vgadev->pdev->bus->self)
-                                                       vgadev->bridge_has_one_vga = false;
-                                       }
-                                       bus = bus->parent;
+                       /* now iterate the previous devices bridge hierarchy */
+                       /* if the new devices parent bridge is in the other devices
+                          hierarchy then we can't use it to control this device */
+                       while (bus) {
+                               bridge = bus->self;
+                               if (bridge) {
+                                       if (bridge == vgadev->pdev->bus->self)
+                                               vgadev->bridge_has_one_vga = false;
                                }
+                               bus = bus->parent;
                        }
                }
                new_bus = new_bus->parent;
@@ -993,14 +991,20 @@ static ssize_t vga_arb_write(struct file *file, const char __user * buf,
                                uc = &priv->cards[i];
                }
 
-               if (!uc)
-                       return -EINVAL;
+               if (!uc) {
+                       ret_val = -EINVAL;
+                       goto done;
+               }
 
-               if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0)
-                       return -EINVAL;
+               if (io_state & VGA_RSRC_LEGACY_IO && uc->io_cnt == 0) {
+                       ret_val = -EINVAL;
+                       goto done;
+               }
 
-               if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0)
-                       return -EINVAL;
+               if (io_state & VGA_RSRC_LEGACY_MEM && uc->mem_cnt == 0) {
+                       ret_val = -EINVAL;
+                       goto done;
+               }
 
                vga_put(pdev, io_state);
 
index 9ec854a..91be41f 100644 (file)
@@ -315,7 +315,7 @@ config SENSORS_DS1621
 
 config SENSORS_EXYNOS4_TMU
        tristate "Temperature sensor on Samsung EXYNOS4"
-       depends on EXYNOS4_DEV_TMU
+       depends on ARCH_EXYNOS4
        help
          If you say yes here you get support for TMU (Thermal Managment
          Unit) on SAMSUNG EXYNOS4 series of SoC.
index 318e38e..5d760f3 100644 (file)
@@ -160,7 +160,6 @@ MODULE_DEVICE_TABLE(spi, ad7314_id);
 static struct spi_driver ad7314_driver = {
        .driver = {
                .name = "ad7314",
-               .bus = &spi_bus_type,
                .owner = THIS_MODULE,
        },
        .probe = ad7314_probe,
index 5231934..04450f8 100644 (file)
@@ -227,7 +227,6 @@ static int __devexit ads7871_remove(struct spi_device *spi)
 static struct spi_driver ads7871_driver = {
        .driver = {
                .name = DEVICE_NAME,
-               .bus = &spi_bus_type,
                .owner = THIS_MODULE,
        },
 
index faa0884..f2359a0 100644 (file)
@@ -506,17 +506,7 @@ static struct platform_driver exynos4_tmu_driver = {
        .resume = exynos4_tmu_resume,
 };
 
-static int __init exynos4_tmu_driver_init(void)
-{
-       return platform_driver_register(&exynos4_tmu_driver);
-}
-module_init(exynos4_tmu_driver_init);
-
-static void __exit exynos4_tmu_driver_exit(void)
-{
-       platform_driver_unregister(&exynos4_tmu_driver);
-}
-module_exit(exynos4_tmu_driver_exit);
+module_platform_driver(exynos4_tmu_driver);
 
 MODULE_DESCRIPTION("EXYNOS4 TMU Driver");
 MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>");
index 89aa9fb..9ba38f3 100644 (file)
@@ -539,18 +539,7 @@ static struct platform_driver gpio_fan_driver = {
        },
 };
 
-static int __init gpio_fan_init(void)
-{
-       return platform_driver_register(&gpio_fan_driver);
-}
-
-static void __exit gpio_fan_exit(void)
-{
-       platform_driver_unregister(&gpio_fan_driver);
-}
-
-module_init(gpio_fan_init);
-module_exit(gpio_fan_exit);
+module_platform_driver(gpio_fan_driver);
 
 MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");
 MODULE_DESCRIPTION("GPIO FAN driver");
index fea292d..7a48b1e 100644 (file)
@@ -212,17 +212,7 @@ struct platform_driver jz4740_hwmon_driver = {
        },
 };
 
-static int __init jz4740_hwmon_init(void)
-{
-       return platform_driver_register(&jz4740_hwmon_driver);
-}
-module_init(jz4740_hwmon_init);
-
-static void __exit jz4740_hwmon_exit(void)
-{
-       platform_driver_unregister(&jz4740_hwmon_driver);
-}
-module_exit(jz4740_hwmon_exit);
+module_platform_driver(jz4740_hwmon_driver);
 
 MODULE_DESCRIPTION("JZ4740 SoC HWMON driver");
 MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
index eab1161..9b382ec 100644 (file)
@@ -432,19 +432,7 @@ static struct platform_driver ntc_thermistor_driver = {
        .id_table = ntc_thermistor_id,
 };
 
-static int __init ntc_thermistor_init(void)
-{
-       return platform_driver_register(&ntc_thermistor_driver);
-}
-
-module_init(ntc_thermistor_init);
-
-static void __exit ntc_thermistor_cleanup(void)
-{
-       platform_driver_unregister(&ntc_thermistor_driver);
-}
-
-module_exit(ntc_thermistor_cleanup);
+module_platform_driver(ntc_thermistor_driver);
 
 MODULE_DESCRIPTION("NTC Thermistor Driver");
 MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
index b39f52e..f6c26d1 100644 (file)
@@ -393,18 +393,7 @@ static struct platform_driver s3c_hwmon_driver = {
        .remove         = __devexit_p(s3c_hwmon_remove),
 };
 
-static int __init s3c_hwmon_init(void)
-{
-       return platform_driver_register(&s3c_hwmon_driver);
-}
-
-static void __exit s3c_hwmon_exit(void)
-{
-       platform_driver_unregister(&s3c_hwmon_driver);
-}
-
-module_init(s3c_hwmon_init);
-module_exit(s3c_hwmon_exit);
+module_platform_driver(s3c_hwmon_driver);
 
 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 MODULE_DESCRIPTION("S3C ADC HWMon driver");
index e3b5c60..79b6dab 100644 (file)
@@ -590,19 +590,8 @@ static struct platform_driver sch5627_driver = {
        .remove         = sch5627_remove,
 };
 
-static int __init sch5627_init(void)
-{
-       return platform_driver_register(&sch5627_driver);
-}
-
-static void __exit sch5627_exit(void)
-{
-       platform_driver_unregister(&sch5627_driver);
-}
+module_platform_driver(sch5627_driver);
 
 MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
-
-module_init(sch5627_init);
-module_exit(sch5627_exit);
index 244407a..9d5236f 100644 (file)
@@ -521,19 +521,8 @@ static struct platform_driver sch5636_driver = {
        .remove         = sch5636_remove,
 };
 
-static int __init sch5636_init(void)
-{
-       return platform_driver_register(&sch5636_driver);
-}
-
-static void __exit sch5636_exit(void)
-{
-       platform_driver_unregister(&sch5636_driver);
-}
+module_platform_driver(sch5636_driver);
 
 MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_LICENSE("GPL");
-
-module_init(sch5636_init);
-module_exit(sch5636_exit);
index 5724074..0018c7d 100644 (file)
@@ -136,19 +136,7 @@ static struct platform_driver twl4030_madc_hwmon_driver = {
                   },
 };
 
-static int __init twl4030_madc_hwmon_init(void)
-{
-       return platform_driver_register(&twl4030_madc_hwmon_driver);
-}
-
-module_init(twl4030_madc_hwmon_init);
-
-static void __exit twl4030_madc_hwmon_exit(void)
-{
-       platform_driver_unregister(&twl4030_madc_hwmon_driver);
-}
-
-module_exit(twl4030_madc_hwmon_exit);
+module_platform_driver(twl4030_madc_hwmon_driver);
 
 MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver");
 MODULE_LICENSE("GPL");
index 3cd07bf..b9a87e8 100644 (file)
@@ -309,15 +309,4 @@ static struct platform_driver env_driver = {
        .remove         = __devexit_p(env_remove),
 };
 
-static int __init env_init(void)
-{
-       return platform_driver_register(&env_driver);
-}
-
-static void __exit env_exit(void)
-{
-       platform_driver_unregister(&env_driver);
-}
-
-module_init(env_init);
-module_exit(env_exit);
+module_platform_driver(env_driver);
index 97b1f83..9b598ed 100644 (file)
@@ -209,17 +209,7 @@ static struct platform_driver wm831x_hwmon_driver = {
        },
 };
 
-static int __init wm831x_hwmon_init(void)
-{
-       return platform_driver_register(&wm831x_hwmon_driver);
-}
-module_init(wm831x_hwmon_init);
-
-static void __exit wm831x_hwmon_exit(void)
-{
-       platform_driver_unregister(&wm831x_hwmon_driver);
-}
-module_exit(wm831x_hwmon_exit);
+module_platform_driver(wm831x_hwmon_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM831x Hardware Monitoring");
index 1329059..3ff67ed 100644 (file)
@@ -133,17 +133,7 @@ static struct platform_driver wm8350_hwmon_driver = {
        },
 };
 
-static int __init wm8350_hwmon_init(void)
-{
-       return platform_driver_register(&wm8350_hwmon_driver);
-}
-module_init(wm8350_hwmon_init);
-
-static void __exit wm8350_hwmon_exit(void)
-{
-       platform_driver_unregister(&wm8350_hwmon_driver);
-}
-module_exit(wm8350_hwmon_exit);
+module_platform_driver(wm8350_hwmon_driver);
 
 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
 MODULE_DESCRIPTION("WM8350 Hardware Monitoring");
index 143461a..86980fe 100644 (file)
@@ -21,6 +21,7 @@
  * General Public License for more details.
  */
 
+#include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
@@ -108,10 +109,8 @@ static int __devinit u8500_hsem_probe(struct platform_device *pdev)
                return -ENODEV;
 
        io_base = ioremap(res->start, resource_size(res));
-       if (!io_base) {
-               ret = -ENOMEM;
-               goto free_state;
-       }
+       if (!io_base)
+               return -ENOMEM;
 
        /* make sure protocol 1 is selected */
        val = readl(io_base + HSEM_CTRL_REG);
index 85584a5..525c734 100644 (file)
@@ -488,7 +488,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 
        if (flags & I2C_M_TEN) {
                /* a ten bit address */
-               addr = 0xf0 | ((msg->addr >> 7) & 0x03);
+               addr = 0xf0 | ((msg->addr >> 7) & 0x06);
                bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr);
                /* try extended address code...*/
                ret = try_address(i2c_adap, addr, retries);
@@ -498,7 +498,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
                        return -ENXIO;
                }
                /* the remaining 8 bit address */
-               ret = i2c_outb(i2c_adap, msg->addr & 0x7f);
+               ret = i2c_outb(i2c_adap, msg->addr & 0xff);
                if ((ret != 1) && !nak_ok) {
                        /* the chip did not ack / xmission error occurred */
                        dev_err(&i2c_adap->dev, "died at 2nd address code\n");
index 835e47b..03b6157 100644 (file)
@@ -593,7 +593,7 @@ static int __devinit nuc900_i2c_probe(struct platform_device *pdev)
        i2c->adap.algo_data = i2c;
        i2c->adap.dev.parent = &pdev->dev;
 
-       mfp_set_groupg(&pdev->dev);
+       mfp_set_groupg(&pdev->dev, NULL);
 
        clk_get_rate(i2c->clk);
 
index 131079a..1e56061 100644 (file)
@@ -539,8 +539,10 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
        client->dev.type = &i2c_client_type;
        client->dev.of_node = info->of_node;
 
+       /* For 10-bit clients, add an arbitrary offset to avoid collisions */
        dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
-                    client->addr);
+                    client->addr | ((client->flags & I2C_CLIENT_TEN)
+                                    ? 0xa000 : 0));
        status = device_register(&client->dev);
        if (status)
                goto out_err;
index c90ce50..57a45ce 100644 (file)
@@ -579,7 +579,7 @@ static int i2cdev_detach_adapter(struct device *dev, void *dummy)
        return 0;
 }
 
-int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
+static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
                         void *data)
 {
        struct device *dev = data;
index 67cbcfa..847553f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1998-2000 Andreas S. Krebs (akrebs@altavista.net), Maintainer
  *  Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>, Integrator
- *  Copyright (C) 2007-2010 Bartlomiej Zolnierkiewicz
+ *  Copyright (C) 2007-2011 Bartlomiej Zolnierkiewicz
  *
  * CYPRESS CY82C693 chipset IDE controller
  *
@@ -90,7 +90,7 @@ static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
        u8 time_16, time_8;
 
        /* select primary or secondary channel */
-       if (hwif->index > 0) {  /* drive is on the secondary channel */
+       if (drive->dn > 1) {  /* drive is on the secondary channel */
                dev = pci_get_slot(dev->bus, dev->devfn+1);
                if (!dev) {
                        printk(KERN_ERR "%s: tune_drive: "
@@ -141,7 +141,7 @@ static void cy82c693_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive)
                pci_write_config_byte(dev, CY82_IDE_SLAVE_IOW, time_16);
                pci_write_config_byte(dev, CY82_IDE_SLAVE_8BIT, time_8);
        }
-       if (hwif->index > 0)
+       if (drive->dn > 1)
                pci_dev_put(dev);
 }
 
index 4a697a2..8716066 100644 (file)
@@ -521,8 +521,8 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
        if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) {
                d.init_dma = icside_dma_init;
                d.port_ops = &icside_v6_port_ops;
+       } else
                d.dma_ops = NULL;
-       }
 
        ret = ide_host_register(host, &d, hws);
        if (ret)
index 04b0956..8126824 100644 (file)
@@ -43,7 +43,6 @@
 /* For SCSI -> ATAPI command conversion */
 #include <scsi/scsi.h>
 
-#include <linux/irq.h>
 #include <linux/io.h>
 #include <asm/byteorder.h>
 #include <linux/uaccess.h>
index 61fdf54..3d42043 100644 (file)
@@ -35,7 +35,6 @@
 #include <scsi/scsi_ioctl.h>
 
 #include <asm/byteorder.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/unaligned.h>
index 7ecb1ad..ce8237d 100644 (file)
@@ -41,7 +41,6 @@
 #include <scsi/scsi.h>
 
 #include <asm/byteorder.h>
-#include <linux/irq.h>
 #include <linux/uaccess.h>
 #include <linux/io.h>
 #include <asm/unaligned.h>
index b59d04c..1892e81 100644 (file)
@@ -331,7 +331,7 @@ static const struct ide_port_ops ich_port_ops = {
                .udma_mask      = udma,                 \
        }
 
-#define DECLARE_ICH_DEV(udma) \
+#define DECLARE_ICH_DEV(mwdma, udma) \
        { \
                .name           = DRV_NAME, \
                .init_chipset   = init_chipset_ich, \
@@ -340,7 +340,7 @@ static const struct ide_port_ops ich_port_ops = {
                .port_ops       = &ich_port_ops, \
                .pio_mask       = ATA_PIO4, \
                .swdma_mask     = ATA_SWDMA2_ONLY, \
-               .mwdma_mask     = ATA_MWDMA12_ONLY, \
+               .mwdma_mask     = mwdma, \
                .udma_mask      = udma, \
        }
 
@@ -362,13 +362,15 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = {
        /* 2: PIIX4 */
        DECLARE_PIIX_DEV(ATA_UDMA2),
        /* 3: ICH0 */
-       DECLARE_ICH_DEV(ATA_UDMA2),
+       DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA2),
        /* 4: ICH */
-       DECLARE_ICH_DEV(ATA_UDMA4),
+       DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA4),
        /* 5: PIIX4 */
        DECLARE_PIIX_DEV(ATA_UDMA4),
-       /* 6: ICH[2-7]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
-       DECLARE_ICH_DEV(ATA_UDMA5),
+       /* 6: ICH[2-6]/ICH[2-3]M/C-ICH/ICH5-SATA/ESB2/ICH8M */
+       DECLARE_ICH_DEV(ATA_MWDMA12_ONLY, ATA_UDMA5),
+       /* 7: ICH7/7-R, no MWDMA1 */
+       DECLARE_ICH_DEV(ATA_MWDMA2_ONLY, ATA_UDMA5),
 };
 
 /**
@@ -438,9 +440,9 @@ static const struct pci_device_id piix_pci_tbl[] = {
 #endif
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB_2),      6 },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH6_19),    6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH7_21),    7 },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_82801DB_1),  6 },
-       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    6 },
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ESB2_18),    7 },
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ICH8_6),     6 },
        { 0, },
 };
index e53a1b7..281c914 100644 (file)
@@ -113,12 +113,26 @@ static const struct pci_device_id triflex_pci_tbl[] = {
 };
 MODULE_DEVICE_TABLE(pci, triflex_pci_tbl);
 
+#ifdef CONFIG_PM
+static int triflex_ide_pci_suspend(struct pci_dev *dev, pm_message_t state)
+{
+       /*
+        * We must not disable or powerdown the device.
+        * APM bios refuses to suspend if IDE is not accessible.
+        */
+       pci_save_state(dev);
+       return 0;
+}
+#else
+#define triflex_ide_pci_suspend NULL
+#endif
+
 static struct pci_driver triflex_pci_driver = {
        .name           = "TRIFLEX_IDE",
        .id_table       = triflex_pci_tbl,
        .probe          = triflex_init_one,
        .remove         = ide_pci_remove,
-       .suspend        = ide_pci_suspend,
+       .suspend        = triflex_ide_pci_suspend,
        .resume         = ide_pci_resume,
 };
 
index 691276b..e9cf51b 100644 (file)
@@ -216,7 +216,9 @@ static int addr4_resolve(struct sockaddr_in *src_in,
 
        neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
        if (!neigh || !(neigh->nud_state & NUD_VALID)) {
+               rcu_read_lock();
                neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
+               rcu_read_unlock();
                ret = -ENODATA;
                if (neigh)
                        goto release;
@@ -274,15 +276,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in,
                goto put;
        }
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
        if (!neigh || !(neigh->nud_state & NUD_VALID)) {
                if (neigh)
                        neigh_event_send(neigh, NULL);
                ret = -ENODATA;
-               goto put;
+       } else {
+               ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
        }
-
-       ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
+       rcu_read_unlock();
 put:
        dst_release(dst);
        return ret;
index de6d077..c88b12b 100644 (file)
@@ -1375,8 +1375,10 @@ static int pass_accept_req(struct t3cdev *tdev, struct sk_buff *skb, void *ctx)
                goto reject;
        }
        dst = &rt->dst;
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
        l2t = t3_l2t_get(tdev, neigh, neigh->dev);
+       rcu_read_unlock();
        if (!l2t) {
                printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
                       __func__);
@@ -1946,10 +1948,12 @@ int iwch_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        }
        ep->dst = &rt->dst;
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(ep->dst);
 
        /* get a l2t entry */
        ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
index b36cdac..0747004 100644 (file)
@@ -542,8 +542,10 @@ static void send_mpa_req(struct c4iw_ep *ep, struct sk_buff *skb,
                     (mpa_rev_to_use == 2 ? MPA_ENHANCED_RDMA_CONN : 0);
        mpa->private_data_size = htons(ep->plen);
        mpa->revision = mpa_rev_to_use;
-       if (mpa_rev_to_use == 1)
+       if (mpa_rev_to_use == 1) {
                ep->tried_with_mpa_v1 = 1;
+               ep->retry_with_mpa_v1 = 0;
+       }
 
        if (mpa_rev_to_use == 2) {
                mpa->private_data_size +=
@@ -1594,6 +1596,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                goto reject;
        }
        dst = &rt->dst;
+       rcu_read_lock();
        neigh = dst_get_neighbour(dst);
        if (neigh->dev->flags & IFF_LOOPBACK) {
                pdev = ip_dev_find(&init_net, peer_ip);
@@ -1620,6 +1623,7 @@ static int pass_accept_req(struct c4iw_dev *dev, struct sk_buff *skb)
                rss_qid = dev->rdev.lldi.rxq_ids[
                          cxgb4_port_idx(neigh->dev) * step];
        }
+       rcu_read_unlock();
        if (!l2t) {
                printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
                       __func__);
@@ -1820,6 +1824,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
        }
        ep->dst = &rt->dst;
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(ep->dst);
 
        /* get a l2t entry */
@@ -1856,6 +1861,7 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
                ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
                        cxgb4_port_idx(neigh->dev) * step];
        }
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
@@ -2301,6 +2307,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
        }
        ep->dst = &rt->dst;
 
+       rcu_read_lock();
        neigh = dst_get_neighbour(ep->dst);
 
        /* get a l2t entry */
@@ -2339,6 +2346,7 @@ int c4iw_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param)
                ep->retry_with_mpa_v1 = 0;
                ep->tried_with_mpa_v1 = 0;
        }
+       rcu_read_unlock();
        if (!ep->l2t) {
                printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
                err = -ENOMEM;
index f35a935..0f1607c 100644 (file)
@@ -311,7 +311,7 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count)
        while (ptr != cq->sw_pidx) {
                cqe = &cq->sw_queue[ptr];
                if (RQ_TYPE(cqe) && (CQE_OPCODE(cqe) != FW_RI_READ_RESP) &&
-                   (CQE_QPID(cqe) == wq->rq.qid) && cqe_completes_wr(cqe, wq))
+                   (CQE_QPID(cqe) == wq->sq.qid) && cqe_completes_wr(cqe, wq))
                        (*count)++;
                if (++ptr == cq->size)
                        ptr = 0;
index dfce9ea..0a52d72 100644 (file)
@@ -1377,9 +1377,11 @@ static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpi
                neigh_release(neigh);
        }
 
-       if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
+       if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
+               rcu_read_lock();
                neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
-
+               rcu_read_unlock();
+       }
        ip_rt_put(rt);
        return rc;
 }
index 5bd2162..1d58959 100644 (file)
@@ -2307,19 +2307,11 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
                SYM_LSB(IBCCtrlA_0, MaxPktLen);
        ppd->cpspec->ibcctrl_a = ibc; /* without linkcmd or linkinitcmd! */
 
-       /* initially come up waiting for TS1, without sending anything. */
-       val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
-               QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
-
-       ppd->cpspec->ibcctrl_a = val;
        /*
         * Reset the PCS interface to the serdes (and also ibc, which is still
         * in reset from above).  Writes new value of ibcctrl_a as last step.
         */
        qib_7322_mini_pcs_reset(ppd);
-       qib_write_kreg(dd, kr_scratch, 0ULL);
-       /* clear the linkinit cmds */
-       ppd->cpspec->ibcctrl_a &= ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
 
        if (!ppd->cpspec->ibcctrl_b) {
                unsigned lse = ppd->link_speed_enabled;
@@ -2385,6 +2377,14 @@ static int qib_7322_bringup_serdes(struct qib_pportdata *ppd)
        ppd->cpspec->ibcctrl_a |= SYM_MASK(IBCCtrlA_0, IBLinkEn);
        set_vls(ppd);
 
+       /* initially come up DISABLED, without sending anything. */
+       val = ppd->cpspec->ibcctrl_a | (QLOGIC_IB_IBCC_LINKINITCMD_DISABLE <<
+                                       QLOGIC_IB_IBCC_LINKINITCMD_SHIFT);
+       qib_write_kreg_port(ppd, krp_ibcctrl_a, val);
+       qib_write_kreg(dd, kr_scratch, 0ULL);
+       /* clear the linkinit cmds */
+       ppd->cpspec->ibcctrl_a = val & ~SYM_MASK(IBCCtrlA_0, LinkInitCmd);
+
        /* be paranoid against later code motion, etc. */
        spin_lock_irqsave(&dd->cspec->rcvmod_lock, flags);
        ppd->p_rcvctrl |= SYM_MASK(RcvCtrl_0, RcvIBPortEnable);
@@ -5241,7 +5241,7 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs)
                           off */
                        if (ppd->dd->flags & QIB_HAS_QSFP) {
                                qd->t_insert = get_jiffies_64();
-                               schedule_work(&qd->work);
+                               queue_work(ib_wq, &qd->work);
                        }
                        spin_lock_irqsave(&ppd->sdma_lock, flags);
                        if (__qib_sdma_running(ppd))
index e06c4ed..fa71b1e 100644 (file)
@@ -480,18 +480,6 @@ void qib_qsfp_init(struct qib_qsfp_data *qd,
        udelay(20); /* Generous RST dwell */
 
        dd->f_gpio_mod(dd, mask, mask, mask);
-       /* Spec says module can take up to two seconds! */
-       mask = QSFP_GPIO_MOD_PRS_N;
-       if (qd->ppd->hw_pidx)
-               mask <<= QSFP_GPIO_PORT2_SHIFT;
-
-       /* Do not try to wait here. Better to let event handle it */
-       if (!qib_qsfp_mod_present(qd->ppd))
-               goto bail;
-       /* We see a module, but it may be unwise to look yet. Just schedule */
-       qd->t_insert = get_jiffies_64();
-       queue_work(ib_wq, &qd->work);
-bail:
        return;
 }
 
index 0ef9af9..4115be5 100644 (file)
@@ -57,21 +57,24 @@ struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
                                 struct ib_pd *pd, struct ib_ah_attr *attr)
 {
        struct ipoib_ah *ah;
+       struct ib_ah *vah;
 
        ah = kmalloc(sizeof *ah, GFP_KERNEL);
        if (!ah)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        ah->dev       = dev;
        ah->last_send = 0;
        kref_init(&ah->ref);
 
-       ah->ah = ib_create_ah(pd, attr);
-       if (IS_ERR(ah->ah)) {
+       vah = ib_create_ah(pd, attr);
+       if (IS_ERR(vah)) {
                kfree(ah);
-               ah = NULL;
-       } else
+               ah = (struct ipoib_ah *)vah;
+       } else {
+               ah->ah = vah;
                ipoib_dbg(netdev_priv(dev), "Created ah %p\n", ah->ah);
+       }
 
        return ah;
 }
index 7567b60..83695b4 100644 (file)
@@ -432,7 +432,7 @@ static void path_rec_completion(int status,
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       if (ah) {
+       if (!IS_ERR_OR_NULL(ah)) {
                path->pathrec = *pathrec;
 
                old_ah   = path->ah;
@@ -555,6 +555,7 @@ static int path_rec_start(struct net_device *dev,
        return 0;
 }
 
+/* called with rcu_read_lock */
 static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -636,6 +637,7 @@ err_drop:
        spin_unlock_irqrestore(&priv->lock, flags);
 }
 
+/* called with rcu_read_lock */
 static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
 {
        struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
@@ -720,13 +722,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
        struct neighbour *n = NULL;
        unsigned long flags;
 
+       rcu_read_lock();
        if (likely(skb_dst(skb)))
                n = dst_get_neighbour(skb_dst(skb));
 
        if (likely(n)) {
                if (unlikely(!*to_ipoib_neigh(n))) {
                        ipoib_path_lookup(skb, dev);
-                       return NETDEV_TX_OK;
+                       goto unlock;
                }
 
                neigh = *to_ipoib_neigh(n);
@@ -749,17 +752,17 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                        ipoib_neigh_free(dev, neigh);
                        spin_unlock_irqrestore(&priv->lock, flags);
                        ipoib_path_lookup(skb, dev);
-                       return NETDEV_TX_OK;
+                       goto unlock;
                }
 
                if (ipoib_cm_get(neigh)) {
                        if (ipoib_cm_up(neigh)) {
                                ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
-                               return NETDEV_TX_OK;
+                               goto unlock;
                        }
                } else if (neigh->ah) {
                        ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
-                       return NETDEV_TX_OK;
+                       goto unlock;
                }
 
                if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
@@ -793,13 +796,14 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev)
                                           phdr->hwaddr + 4);
                                dev_kfree_skb_any(skb);
                                ++dev->stats.tx_dropped;
-                               return NETDEV_TX_OK;
+                               goto unlock;
                        }
 
                        unicast_arp_send(skb, dev, phdr);
                }
        }
-
+unlock:
+       rcu_read_unlock();
        return NETDEV_TX_OK;
 }
 
@@ -837,7 +841,7 @@ static int ipoib_hard_header(struct sk_buff *skb,
        dst = skb_dst(skb);
        n = NULL;
        if (dst)
-               n = dst_get_neighbour(dst);
+               n = dst_get_neighbour_raw(dst);
        if ((!dst || !n) && daddr) {
                struct ipoib_pseudoheader *phdr =
                        (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
index 1b7a976..873bff9 100644 (file)
@@ -240,8 +240,11 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
                av.grh.dgid = mcast->mcmember.mgid;
 
                ah = ipoib_create_ah(dev, priv->pd, &av);
-               if (!ah) {
-                       ipoib_warn(priv, "ib_address_create failed\n");
+               if (IS_ERR(ah)) {
+                       ipoib_warn(priv, "ib_address_create failed %ld\n",
+                               -PTR_ERR(ah));
+                       /* use original error */
+                       return PTR_ERR(ah);
                } else {
                        spin_lock_irq(&priv->lock);
                        mcast->ah = ah;
@@ -266,7 +269,7 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast,
 
                skb->dev = dev;
                if (dst)
-                       n = dst_get_neighbour(dst);
+                       n = dst_get_neighbour_raw(dst);
                if (!dst || !n) {
                        /* put pseudoheader back on for next time */
                        skb_push(skb, sizeof (struct ipoib_pseudoheader));
@@ -722,6 +725,8 @@ out:
        if (mcast && mcast->ah) {
                struct dst_entry *dst = skb_dst(skb);
                struct neighbour *n = NULL;
+
+               rcu_read_lock();
                if (dst)
                        n = dst_get_neighbour(dst);
                if (n && !*to_ipoib_neigh(n)) {
@@ -734,7 +739,7 @@ out:
                                list_add_tail(&neigh->list, &mcast->neigh_list);
                        }
                }
-
+               rcu_read_unlock();
                spin_unlock_irqrestore(&priv->lock, flags);
                ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
                return;
index 09b93b1..e2a9867 100644 (file)
@@ -1210,18 +1210,28 @@ static int elantech_reconnect(struct psmouse *psmouse)
  */
 static int elantech_set_properties(struct elantech_data *etd)
 {
+       /* This represents the version of IC body. */
        int ver = (etd->fw_version & 0x0f0000) >> 16;
 
+       /* Early version of Elan touchpads doesn't obey the rule. */
        if (etd->fw_version < 0x020030 || etd->fw_version == 0x020600)
                etd->hw_version = 1;
-       else if (etd->fw_version < 0x150600)
-               etd->hw_version = 2;
-       else if (ver == 5)
-               etd->hw_version = 3;
-       else if (ver == 6)
-               etd->hw_version = 4;
-       else
-               return -1;
+       else {
+               switch (ver) {
+               case 2:
+               case 4:
+                       etd->hw_version = 2;
+                       break;
+               case 5:
+                       etd->hw_version = 3;
+                       break;
+               case 6:
+                       etd->hw_version = 4;
+                       break;
+               default:
+                       return -1;
+               }
+       }
 
        /*
         * Turn on packet checking by default.
index 4b2a42f..d4d08bd 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/irq.h>
 #include <linux/serio.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include <asm/mach-types.h>
 #include <plat/board-ams-delta.h>
index bb9f5d3..b4cfc6c 100644 (file)
@@ -431,6 +431,13 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
                },
        },
+       {
+               /* Newer HP Pavilion dv4 models */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+               },
+       },
        { }
 };
 
@@ -560,6 +567,13 @@ static const struct dmi_system_id __initconst i8042_dmi_notimeout_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V13"),
                },
        },
+       {
+               /* Newer HP Pavilion dv4 models */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4 Notebook PC"),
+               },
+       },
        { }
 };
 
index 9c192e7..288da5c 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
index e8fdb88..46be456 100644 (file)
@@ -10,6 +10,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/module.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
index 33ec9e4..9021182 100644 (file)
@@ -242,6 +242,12 @@ static int isdn_divert_ioctl_unlocked(struct file *file, uint cmd, ulong arg)
                case IIOCDOCFINT:
                        if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
                                return (-EINVAL);       /* invalid driver */
+                       if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) ==
+                                       sizeof(dioctl.cf_ctrl.msn))
+                               return -EINVAL;
+                       if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) ==
+                                       sizeof(dioctl.cf_ctrl.fwd_nr))
+                               return -EINVAL;
                        if ((i = cf_command(dioctl.cf_ctrl.drvid,
                                            (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
                                            dioctl.cf_ctrl.cfproc,
index 1f73d7f..2339d73 100644 (file)
@@ -2756,6 +2756,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
                        char *c,
                        *e;
 
+                       if (strnlen(cfg->drvid, sizeof(cfg->drvid)) ==
+                                       sizeof(cfg->drvid))
+                               return -EINVAL;
                        drvidx = -1;
                        chidx = -1;
                        strcpy(drvid, cfg->drvid);
index 661b692..6d5628b 100644 (file)
@@ -270,11 +270,8 @@ void led_blink_set(struct led_classdev *led_cdev,
        del_timer_sync(&led_cdev->blink_timer);
 
        if (led_cdev->blink_set &&
-           !led_cdev->blink_set(led_cdev, delay_on, delay_off)) {
-               led_cdev->blink_delay_on = *delay_on;
-               led_cdev->blink_delay_off = *delay_off;
+           !led_cdev->blink_set(led_cdev, delay_on, delay_off))
                return;
-       }
 
        /* blink with 1 Hz as default if nothing specified */
        if (!*delay_on && !*delay_off)
index 817f37a..c9570fc 100644 (file)
@@ -159,7 +159,7 @@ int macii_init(void)
        err = macii_init_via();
        if (err) goto out;
 
-       err = request_irq(IRQ_MAC_ADB, macii_interrupt, IRQ_FLG_LOCK, "ADB",
+       err = request_irq(IRQ_MAC_ADB, macii_interrupt, 0, "ADB",
                          macii_interrupt);
        if (err) goto out;
 
index 9ab5b0c..34d02a9 100644 (file)
@@ -122,8 +122,8 @@ maciisi_init(void)
                return err;
        }
 
-       if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, IRQ_FLG_LOCK | IRQ_FLG_FAST, 
-                       "ADB", maciisi_interrupt)) {
+       if (request_irq(IRQ_MAC_ADB, maciisi_interrupt, 0, "ADB",
+                       maciisi_interrupt)) {
                printk(KERN_ERR "maciisi_init: can't get irq %d\n", IRQ_MAC_ADB);
                return -EAGAIN;
        }
index 472aedf..297e260 100644 (file)
@@ -3110,7 +3110,7 @@ static void handle_stripe(struct stripe_head *sh)
        struct r5dev *pdev, *qdev;
 
        clear_bit(STRIPE_HANDLE, &sh->state);
-       if (test_and_set_bit(STRIPE_ACTIVE, &sh->state)) {
+       if (test_and_set_bit_lock(STRIPE_ACTIVE, &sh->state)) {
                /* already being handled, ensure it gets handled
                 * again when current action finishes */
                set_bit(STRIPE_HANDLE, &sh->state);
@@ -3159,10 +3159,14 @@ static void handle_stripe(struct stripe_head *sh)
        /* check if the array has lost more than max_degraded devices and,
         * if so, some requests might need to be failed.
         */
-       if (s.failed > conf->max_degraded && s.to_read+s.to_write+s.written)
-               handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
-       if (s.failed > conf->max_degraded && s.syncing)
-               handle_failed_sync(conf, sh, &s);
+       if (s.failed > conf->max_degraded) {
+               sh->check_state = 0;
+               sh->reconstruct_state = 0;
+               if (s.to_read+s.to_write+s.written)
+                       handle_failed_stripe(conf, sh, &s, disks, &s.return_bi);
+               if (s.syncing)
+                       handle_failed_sync(conf, sh, &s);
+       }
 
        /*
         * might be able to return some write requests if the parity blocks
@@ -3371,7 +3375,7 @@ finish:
 
        return_io(s.return_bi);
 
-       clear_bit(STRIPE_ACTIVE, &sh->state);
+       clear_bit_unlock(STRIPE_ACTIVE, &sh->state);
 }
 
 static void raid5_activate_delayed(struct r5conf *conf)
index 2e8c288..3443455 100644 (file)
@@ -398,7 +398,6 @@ static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
        u8 i2c_r_data[24];
        u8 i = 0;
        u8 fifo_status = 0;
-       int ret;
        int status = 0;
 
        mxl_i2c("read %d bytes", count);
@@ -418,7 +417,7 @@ static int mxl111sf_i2c_readagain(struct mxl111sf_state *state,
                i2c_w_data[4+(i*3)] = 0x00;
        }
 
-       ret = mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
+       mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data);
 
        /* Check for I2C NACK status */
        if (mxl111sf_i2c_check_status(state) == 1) {
index 91dc1fc..b741b3a 100644 (file)
@@ -296,8 +296,7 @@ int mxl111sf_config_spi(struct mxl111sf_state *state, int onoff)
                goto fail;
 
        ret = mxl111sf_write_reg(state, 0x00, 0x00);
-       if (mxl_fail(ret))
-               goto fail;
+       mxl_fail(ret);
 fail:
        return ret;
 }
@@ -328,11 +327,13 @@ int mxl111sf_idac_config(struct mxl111sf_state *state,
                /* set hysteresis value  reg: 0x0B<5:0> */
                ret = mxl111sf_write_reg(state, V6_IDAC_HYSTERESIS_REG,
                                         (hysteresis_value & 0x3F));
+               mxl_fail(ret);
        }
 
        ret = mxl111sf_write_reg(state, V6_IDAC_SETTINGS_REG, val);
+       mxl_fail(ret);
 
-       return val;
+       return ret;
 }
 
 /*
index 2446736..0df7f2a 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/media.h>
+#include <linux/module.h>
 #include <linux/regulator/consumer.h>
 #include <linux/slab.h>
 
index 725634d..844a4d7 100644 (file)
@@ -220,8 +220,8 @@ static int vidioc_querycap(struct file *file, void *priv,
        strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
        cap->bus_info[0] = 0;
        cap->version = KERNEL_VERSION(1, 0, 0);
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT
-                                                   | V4L2_CAP_STREAMING;
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+                       V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
        return 0;
 }
 
index ecef127..1e8cdb7 100644 (file)
@@ -785,8 +785,8 @@ static int vidioc_querycap(struct file *file, void *priv,
        strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
        cap->bus_info[0] = 0;
        cap->version = KERNEL_VERSION(1, 0, 0);
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
-                         | V4L2_CAP_VIDEO_OUTPUT
+       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE_MPLANE
+                         | V4L2_CAP_VIDEO_OUTPUT_MPLANE
                          | V4L2_CAP_STREAMING;
        return 0;
 }
index 10c2364..254d326 100644 (file)
@@ -1016,7 +1016,8 @@ int uvc_query_v4l2_menu(struct uvc_video_chain *chain,
 
        menu_info = &mapping->menu_info[query_menu->index];
 
-       if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+       if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+           (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
                s32 bitmap;
 
                if (!ctrl->cached) {
@@ -1225,7 +1226,8 @@ int uvc_ctrl_set(struct uvc_video_chain *chain,
                /* Valid menu indices are reported by the GET_RES request for
                 * UVC controls that support it.
                 */
-               if (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES) {
+               if (mapping->data_type == UVC_CTRL_DATA_TYPE_BITMASK &&
+                   (ctrl->info.flags & UVC_CTRL_FLAG_GET_RES)) {
                        if (!ctrl->cached) {
                                ret = uvc_ctrl_populate_cache(chain, ctrl);
                                if (ret < 0)
index f17f92b..0f415da 100644 (file)
@@ -821,8 +821,8 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
        fill_event(&ev, ctrl, changes);
 
        list_for_each_entry(sev, &ctrl->ev_subs, node)
-               if (sev->fh && (sev->fh != fh ||
-                               (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK)))
+               if (sev->fh != fh ||
+                   (sev->flags & V4L2_EVENT_SUB_FL_ALLOW_FEEDBACK))
                        v4l2_event_queue_fh(sev->fh, &ev);
 }
 
@@ -947,6 +947,7 @@ static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
                        if (ctrl->cluster[0]->has_volatiles)
                                ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
                }
+               fh = NULL;
        }
        if (changed || update_inactive) {
                /* If a control was changed that was not one of the controls
index 46037f2..c26ad96 100644 (file)
@@ -216,6 +216,9 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,
        unsigned long flags;
        unsigned i;
 
+       if (sub->type == V4L2_EVENT_ALL)
+               return -EINVAL;
+
        if (elems < 1)
                elems = 1;
        if (sub->type == V4L2_EVENT_CTRL) {
@@ -283,6 +286,7 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
 {
        struct v4l2_subscribed_event *sev;
        unsigned long flags;
+       int i;
 
        if (sub->type == V4L2_EVENT_ALL) {
                v4l2_event_unsubscribe_all(fh);
@@ -293,8 +297,12 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,
 
        sev = v4l2_event_subscribed(fh, sub->type, sub->id);
        if (sev != NULL) {
+               /* Remove any pending events for this subscription */
+               for (i = 0; i < sev->in_use; i++) {
+                       list_del(&sev->events[sev_pos(sev, i)].list);
+                       fh->navailable--;
+               }
                list_del(&sev->list);
-               sev->fh = NULL;
        }
 
        spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
index 979e544..95a3f5e 100644 (file)
@@ -131,6 +131,7 @@ static void __setup_offsets(struct vb2_queue *q, unsigned int n)
                        continue;
 
                for (plane = 0; plane < vb->num_planes; ++plane) {
+                       vb->v4l2_planes[plane].length = q->plane_sizes[plane];
                        vb->v4l2_planes[plane].m.mem_offset = off;
 
                        dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n",
@@ -264,6 +265,7 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
        q->num_buffers -= buffers;
        if (!q->num_buffers)
                q->memory = 0;
+       INIT_LIST_HEAD(&q->queued_list);
 }
 
 /**
@@ -296,14 +298,14 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
 {
        unsigned int plane;
        for (plane = 0; plane < vb->num_planes; ++plane) {
+               void *mem_priv = vb->planes[plane].mem_priv;
                /*
                 * If num_users() has not been provided, call_memop
                 * will return 0, apparently nobody cares about this
                 * case anyway. If num_users() returns more than 1,
                 * we are not the only user of the plane's memory.
                 */
-               if (call_memop(q, plane, num_users,
-                               vb->planes[plane].mem_priv) > 1)
+               if (mem_priv && call_memop(q, plane, num_users, mem_priv) > 1)
                        return true;
        }
        return false;
index 4175544..ec10629 100644 (file)
@@ -13,6 +13,7 @@
  * TODO: Event handling with irq_chip. Waiting for PRCMU fw support.
  */
 
+#include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
index 6be1fe6..43c0ebb 100644 (file)
@@ -4,6 +4,7 @@
  * Debugfs support for the AB5500 MFD driver
  */
 
+#include <linux/export.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/mfd/ab5500/ab5500.h>
index d593878..5664696 100644 (file)
@@ -472,7 +472,7 @@ config BMP085
          module will be called bmp085.
 
 config PCH_PHUB
-       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB"
+       tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) PHUB"
        depends on PCI
        help
          This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
@@ -480,12 +480,13 @@ config PCH_PHUB
          processor. The Topcliff has MAC address and Option ROM data in SROM.
          This driver can access MAC address and Option ROM data in SROM.
 
-         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
-         Output Hub), ML7213 and ML7223.
-         ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
-         for MP(Media Phone) use.
-         ML7213/ML7223 is companion chip for Intel Atom E6xx series.
-         ML7213/ML7223 is completely compatible for Intel EG20T PCH.
+         This driver also can be used for LAPIS Semiconductor's IOH,
+         ML7213/ML7223/ML7831.
+         ML7213 which is for IVI(In-Vehicle Infotainment) use.
+         ML7223 IOH is for MP(Media Phone) use.
+         ML7831 IOH is for general purpose use.
+         ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
 
          To compile this driver as a module, choose M here: the module will
          be called pch_phub.
index a662f59..82b2cb7 100644 (file)
@@ -100,7 +100,7 @@ enum dpot_devid {
        AD5293_ID = DPOT_CONF(F_RDACS_RW | F_SPI_16BIT, BRDAC0, 10, 27),
        AD7376_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
                        BRDAC0, 7, 28),
-       AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_8BIT,
+       AD8400_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
                        BRDAC0, 8, 29),
        AD8402_ID = DPOT_CONF(F_RDACS_WONLY | F_AD_APPDATA | F_SPI_16BIT,
                        BRDAC0 | BRDAC1, 8, 30),
index 7ce6065..eb5cd28 100644 (file)
@@ -945,8 +945,7 @@ static int fpga_of_remove(struct platform_device *op)
 /* CTL-CPLD Version Register */
 #define CTL_CPLD_VERSION       0x2000
 
-static int fpga_of_probe(struct platform_device *op,
-                        const struct of_device_id *match)
+static int fpga_of_probe(struct platform_device *op)
 {
        struct device_node *of_node = op->dev.of_node;
        struct device *this_device;
@@ -1107,7 +1106,7 @@ static struct of_device_id fpga_of_match[] = {
        {},
 };
 
-static struct of_platform_driver fpga_of_driver = {
+static struct platform_driver fpga_of_driver = {
        .probe          = fpga_of_probe,
        .remove         = fpga_of_remove,
        .driver         = {
@@ -1124,12 +1123,12 @@ static struct of_platform_driver fpga_of_driver = {
 static int __init fpga_init(void)
 {
        led_trigger_register_simple("fpga", &ledtrig_fpga);
-       return of_register_platform_driver(&fpga_of_driver);
+       return platform_driver_register(&fpga_of_driver);
 }
 
 static void __exit fpga_exit(void)
 {
-       of_unregister_platform_driver(&fpga_of_driver);
+       platform_driver_unregister(&fpga_of_driver);
        led_trigger_unregister_simple(ledtrig_fpga);
 }
 
index 3965821..14e974b 100644 (file)
@@ -1249,8 +1249,7 @@ static bool dma_filter(struct dma_chan *chan, void *data)
        return true;
 }
 
-static int data_of_probe(struct platform_device *op,
-                        const struct of_device_id *match)
+static int data_of_probe(struct platform_device *op)
 {
        struct device_node *of_node = op->dev.of_node;
        struct device *this_device;
@@ -1401,7 +1400,7 @@ static struct of_device_id data_of_match[] = {
        {},
 };
 
-static struct of_platform_driver data_of_driver = {
+static struct platform_driver data_of_driver = {
        .probe          = data_of_probe,
        .remove         = data_of_remove,
        .driver         = {
@@ -1417,12 +1416,12 @@ static struct of_platform_driver data_of_driver = {
 
 static int __init data_init(void)
 {
-       return of_register_platform_driver(&data_of_driver);
+       return platform_driver_register(&data_of_driver);
 }
 
 static void __exit data_exit(void)
 {
-       of_unregister_platform_driver(&data_of_driver);
+       platform_driver_unregister(&data_of_driver);
 }
 
 MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
index 26cf12c..701edf6 100644 (file)
@@ -85,7 +85,7 @@ config EEPROM_93XX46
 
 config EEPROM_DIGSY_MTC_CFG
        bool "DigsyMTC display configuration EEPROMs device"
-       depends on PPC_MPC5200_GPIO && GPIOLIB && SPI_GPIO
+       depends on GPIO_MPC5200 && SPI_GPIO
        help
          This option enables access to display configuration EEPROMs
          on digsy_mtc board. You have to additionally select Microwire
index dee33ad..10fc478 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
  *
  * 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
 #define PCH_PHUB_ROM_START_ADDR_EG20T 0x80 /* ROM data area start address offset
                                              (Intel EG20T PCH)*/
 #define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address
-                                               offset(OKI SEMICONDUCTOR ML7213)
+                                               offset(LAPIS Semicon ML7213)
                                              */
 #define PCH_PHUB_ROM_START_ADDR_ML7223 0x400 /* ROM data area start address
-                                               offset(OKI SEMICONDUCTOR ML7223)
+                                               offset(LAPIS Semicon ML7223)
                                              */
 
 /* MAX number of INT_REDUCE_CONTROL registers */
@@ -73,6 +73,9 @@
 #define PCI_DEVICE_ID_ROHM_ML7223_mPHUB        0x8012 /* for Bus-m */
 #define PCI_DEVICE_ID_ROHM_ML7223_nPHUB        0x8002 /* for Bus-n */
 
+/* Macros for ML7831 */
+#define PCI_DEVICE_ID_ROHM_ML7831_PHUB 0x8801
+
 /* SROM ACCESS Macro */
 #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
 
  * @pch_mac_start_address:             MAC address area start address
  * @pch_opt_rom_start_address:         Option ROM start address
  * @ioh_type:                          Save IOH type
+ * @pdev:                              pointer to pci device struct
  */
 struct pch_phub_reg {
        u32 phub_id_reg;
@@ -136,6 +140,7 @@ struct pch_phub_reg {
        u32 pch_mac_start_address;
        u32 pch_opt_rom_start_address;
        int ioh_type;
+       struct pci_dev *pdev;
 };
 
 /* SROM SPEC for MAC address assignment offset */
@@ -471,7 +476,7 @@ static int pch_phub_write_gbe_mac_addr(struct pch_phub_reg *chip, u8 *data)
        int retval;
        int i;
 
-       if (chip->ioh_type == 1) /* EG20T */
+       if ((chip->ioh_type == 1) || (chip->ioh_type == 5)) /* EG20T or ML7831*/
                retval = pch_phub_gbe_serial_rom_conf(chip);
        else    /* ML7223 */
                retval = pch_phub_gbe_serial_rom_conf_mp(chip);
@@ -498,6 +503,7 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
        unsigned int orom_size;
        int ret;
        int err;
+       ssize_t rom_size;
 
        struct pch_phub_reg *chip =
                dev_get_drvdata(container_of(kobj, struct device, kobj));
@@ -509,6 +515,10 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
        }
 
        /* Get Rom signature */
+       chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+       if (!chip->pch_phub_extrom_base_address)
+               goto exrom_map_err;
+
        pch_phub_read_serial_rom(chip, chip->pch_opt_rom_start_address,
                                (unsigned char *)&rom_signature);
        rom_signature &= 0xff;
@@ -539,10 +549,13 @@ static ssize_t pch_phub_bin_read(struct file *filp, struct kobject *kobj,
                goto return_err;
        }
 return_ok:
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
        mutex_unlock(&pch_phub_mutex);
        return addr_offset;
 
 return_err:
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
+exrom_map_err:
        mutex_unlock(&pch_phub_mutex);
 return_err_nomutex:
        return err;
@@ -555,6 +568,7 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
        int err;
        unsigned int addr_offset;
        int ret;
+       ssize_t rom_size;
        struct pch_phub_reg *chip =
                dev_get_drvdata(container_of(kobj, struct device, kobj));
 
@@ -571,6 +585,12 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
                goto return_ok;
        }
 
+       chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+       if (!chip->pch_phub_extrom_base_address) {
+               err = -ENOMEM;
+               goto exrom_map_err;
+       }
+
        for (addr_offset = 0; addr_offset < count; addr_offset++) {
                if (PCH_PHUB_OROM_SIZE < off + addr_offset)
                        goto return_ok;
@@ -585,10 +605,14 @@ static ssize_t pch_phub_bin_write(struct file *filp, struct kobject *kobj,
        }
 
 return_ok:
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
        mutex_unlock(&pch_phub_mutex);
        return addr_offset;
 
 return_err:
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
+
+exrom_map_err:
        mutex_unlock(&pch_phub_mutex);
        return err;
 }
@@ -598,8 +622,14 @@ static ssize_t show_pch_mac(struct device *dev, struct device_attribute *attr,
 {
        u8 mac[8];
        struct pch_phub_reg *chip = dev_get_drvdata(dev);
+       ssize_t rom_size;
+
+       chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+       if (!chip->pch_phub_extrom_base_address)
+               return -ENOMEM;
 
        pch_phub_read_gbe_mac_addr(chip, mac);
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
 
        return sprintf(buf, "%pM\n", mac);
 }
@@ -608,6 +638,7 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
                             const char *buf, size_t count)
 {
        u8 mac[6];
+       ssize_t rom_size;
        struct pch_phub_reg *chip = dev_get_drvdata(dev);
 
        if (count != 18)
@@ -617,7 +648,12 @@ static ssize_t store_pch_mac(struct device *dev, struct device_attribute *attr,
                (u32 *)&mac[0], (u32 *)&mac[1], (u32 *)&mac[2], (u32 *)&mac[3],
                (u32 *)&mac[4], (u32 *)&mac[5]);
 
+       chip->pch_phub_extrom_base_address = pci_map_rom(chip->pdev, &rom_size);
+       if (!chip->pch_phub_extrom_base_address)
+               return -ENOMEM;
+
        pch_phub_write_gbe_mac_addr(chip, mac);
+       pci_unmap_rom(chip->pdev, chip->pch_phub_extrom_base_address);
 
        return count;
 }
@@ -640,7 +676,6 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
        int retval;
 
        int ret;
-       ssize_t rom_size;
        struct pch_phub_reg *chip;
 
        chip = kzalloc(sizeof(struct pch_phub_reg), GFP_KERNEL);
@@ -677,19 +712,7 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
                "in pch_phub_base_address variable is %p\n", __func__,
                chip->pch_phub_base_address);
 
-       if (id->driver_data != 3) {
-               chip->pch_phub_extrom_base_address =\
-                                                  pci_map_rom(pdev, &rom_size);
-               if (chip->pch_phub_extrom_base_address == 0) {
-                       dev_err(&pdev->dev, "%s: pci_map_rom FAILED", __func__);
-                       ret = -ENOMEM;
-                       goto err_pci_map;
-               }
-               dev_dbg(&pdev->dev, "%s : "
-                       "pci_map_rom SUCCESS and value in "
-                       "pch_phub_extrom_base_address variable is %p\n",
-                       __func__, chip->pch_phub_extrom_base_address);
-       }
+       chip->pdev = pdev; /* Save pci device struct */
 
        if (id->driver_data == 1) { /* EG20T PCH */
                const char *board_name;
@@ -763,6 +786,22 @@ static int __devinit pch_phub_probe(struct pci_dev *pdev,
                chip->pch_opt_rom_start_address =\
                                                 PCH_PHUB_ROM_START_ADDR_ML7223;
                chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_ML7223;
+       } else if (id->driver_data == 5) { /* ML7831 */
+               retval = sysfs_create_file(&pdev->dev.kobj,
+                                          &dev_attr_pch_mac.attr);
+               if (retval)
+                       goto err_sysfs_create;
+
+               retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+               if (retval)
+                       goto exit_bin_attr;
+
+               /* set the prefech value */
+               iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
+               /* set the interrupt delay value */
+               iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+               chip->pch_opt_rom_start_address = PCH_PHUB_ROM_START_ADDR_EG20T;
+               chip->pch_mac_start_address = PCH_PHUB_MAC_START_ADDR_EG20T;
        }
 
        chip->ioh_type = id->driver_data;
@@ -773,8 +812,6 @@ exit_bin_attr:
        sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
 
 err_sysfs_create:
-       pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
-err_pci_map:
        pci_iounmap(pdev, chip->pch_phub_base_address);
 err_pci_iomap:
        pci_release_regions(pdev);
@@ -792,7 +829,6 @@ static void __devexit pch_phub_remove(struct pci_dev *pdev)
 
        sysfs_remove_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
        sysfs_remove_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-       pci_unmap_rom(pdev, chip->pch_phub_extrom_base_address);
        pci_iounmap(pdev, chip->pch_phub_base_address);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
@@ -847,6 +883,7 @@ static struct pci_device_id pch_phub_pcidev_id[] = {
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2,  },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_mPHUB), 3,  },
        { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7223_nPHUB), 4,  },
+       { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7831_PHUB), 5,  },
        { }
 };
 MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id);
@@ -873,5 +910,5 @@ static void __exit pch_phub_pci_exit(void)
 module_init(pch_phub_pci_init);
 module_exit(pch_phub_pci_exit);
 
-MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR IOH(ML7213/ML7223) PHUB");
+MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7223) PHUB");
 MODULE_LICENSE("GPL");
index cfbddbe..43d073b 100644 (file)
@@ -903,6 +903,6 @@ static void __exit spear_pcie_gadget_exit(void)
 }
 module_exit(spear_pcie_gadget_exit);
 
-MODULE_ALIAS("pcie-gadget-spear");
+MODULE_ALIAS("platform:pcie-gadget-spear");
 MODULE_AUTHOR("Pratyush Anand");
 MODULE_LICENSE("GPL");
index ae57769..4b976f0 100644 (file)
@@ -32,6 +32,7 @@
 /* VENDOR SPEC register */
 #define SDHCI_VENDOR_SPEC              0xC0
 #define  SDHCI_VENDOR_SPEC_SDIO_QUIRK  0x00000002
+#define SDHCI_WTMK_LVL                 0x44
 #define SDHCI_MIX_CTRL                 0x48
 
 /*
@@ -476,6 +477,13 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev)
        if (is_imx53_esdhc(imx_data))
                imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
 
+       /*
+        * The imx6q ROM code will change the default watermark level setting
+        * to something insane.  Change it back here.
+        */
+       if (is_imx6q_usdhc(imx_data))
+               writel(0x08100810, host->ioaddr + SDHCI_WTMK_LVL);
+
        boarddata = &imx_data->boarddata;
        if (sdhci_esdhc_imx_probe_dt(pdev, boarddata) < 0) {
                if (!host->mmc->parent->platform_data) {
index 608967f..736ca10 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
index 583f66c..654a5e9 100644 (file)
@@ -245,6 +245,8 @@ source "drivers/net/ethernet/Kconfig"
 
 source "drivers/net/fddi/Kconfig"
 
+source "drivers/net/hippi/Kconfig"
+
 config NET_SB1000
        tristate "General Instruments Surfboard 1000"
        depends on PNP
index a73d9dc..84fb634 100644 (file)
@@ -4,7 +4,7 @@
 
 menuconfig ARCNET
        depends on NETDEVICES && (ISA || PCI || PCMCIA)
-       bool "ARCnet support"
+       tristate "ARCnet support"
        ---help---
          If you have a network card of this type, say Y and check out the
          (arguably) beautiful poetry in
index b0c5772..7f87568 100644 (file)
@@ -2553,30 +2553,6 @@ re_arm:
        }
 }
 
-static __be32 bond_glean_dev_ip(struct net_device *dev)
-{
-       struct in_device *idev;
-       struct in_ifaddr *ifa;
-       __be32 addr = 0;
-
-       if (!dev)
-               return 0;
-
-       rcu_read_lock();
-       idev = __in_dev_get_rcu(dev);
-       if (!idev)
-               goto out;
-
-       ifa = idev->ifa_list;
-       if (!ifa)
-               goto out;
-
-       addr = ifa->ifa_local;
-out:
-       rcu_read_unlock();
-       return addr;
-}
-
 static int bond_has_this_ip(struct bonding *bond, __be32 ip)
 {
        struct vlan_entry *vlan;
@@ -3322,6 +3298,10 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
        struct bonding *bond;
        struct vlan_entry *vlan;
 
+       /* we only care about primary address */
+       if(ifa->ifa_flags & IFA_F_SECONDARY)
+               return NOTIFY_DONE;
+
        list_for_each_entry(bond, &bn->dev_list, bond_list) {
                if (bond->dev == event_dev) {
                        switch (event) {
@@ -3329,7 +3309,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
                                bond->master_ip = ifa->ifa_local;
                                return NOTIFY_OK;
                        case NETDEV_DOWN:
-                               bond->master_ip = bond_glean_dev_ip(bond->dev);
+                               bond->master_ip = 0;
                                return NOTIFY_OK;
                        default:
                                return NOTIFY_DONE;
@@ -3345,8 +3325,7 @@ static int bond_inetaddr_event(struct notifier_block *this, unsigned long event,
                                        vlan->vlan_ip = ifa->ifa_local;
                                        return NOTIFY_OK;
                                case NETDEV_DOWN:
-                                       vlan->vlan_ip =
-                                               bond_glean_dev_ip(vlan_dev);
+                                       vlan->vlan_ip = 0;
                                        return NOTIFY_OK;
                                default:
                                        return NOTIFY_DONE;
index 5a20804..4ef7e2f 100644 (file)
@@ -319,6 +319,13 @@ static ssize_t bonding_store_mode(struct device *d,
                goto out;
        }
 
+       if (bond->slave_cnt > 0) {
+               pr_err("unable to update mode of %s because it has slaves.\n",
+                       bond->dev->name);
+               ret = -EPERM;
+               goto out;
+       }
+
        new_value = bond_parse_parm(buf, bond_mode_tbl);
        if (new_value < 0)  {
                pr_err("%s: Ignoring invalid mode value %.*s.\n",
index 905bce0..2c7f503 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
index 4cf835d..3fb66d0 100644 (file)
@@ -608,7 +608,7 @@ static void b44_tx(struct b44 *bp)
                                 skb->len,
                                 DMA_TO_DEVICE);
                rp->skb = NULL;
-               dev_kfree_skb(skb);
+               dev_kfree_skb_irq(skb);
        }
 
        bp->tx_cons = cons;
index bce203f..882f48f 100644 (file)
@@ -10327,6 +10327,43 @@ static int bnx2x_54618se_config_init(struct bnx2x_phy *phy,
        return 0;
 }
 
+
+static void bnx2x_5461x_set_link_led(struct bnx2x_phy *phy,
+                                      struct link_params *params, u8 mode)
+{
+       struct bnx2x *bp = params->bp;
+       u16 temp;
+
+       bnx2x_cl22_write(bp, phy,
+               MDIO_REG_GPHY_SHADOW,
+               MDIO_REG_GPHY_SHADOW_LED_SEL1);
+       bnx2x_cl22_read(bp, phy,
+               MDIO_REG_GPHY_SHADOW,
+               &temp);
+       temp &= 0xff00;
+
+       DP(NETIF_MSG_LINK, "54618x set link led (mode=%x)\n", mode);
+       switch (mode) {
+       case LED_MODE_FRONT_PANEL_OFF:
+       case LED_MODE_OFF:
+               temp |= 0x00ee;
+               break;
+       case LED_MODE_OPER:
+               temp |= 0x0001;
+               break;
+       case LED_MODE_ON:
+               temp |= 0x00ff;
+               break;
+       default:
+               break;
+       }
+       bnx2x_cl22_write(bp, phy,
+               MDIO_REG_GPHY_SHADOW,
+               MDIO_REG_GPHY_SHADOW_WR_ENA | temp);
+       return;
+}
+
+
 static void bnx2x_54618se_link_reset(struct bnx2x_phy *phy,
                                     struct link_params *params)
 {
@@ -11103,7 +11140,7 @@ static struct bnx2x_phy phy_54618se = {
        .config_loopback = (config_loopback_t)bnx2x_54618se_config_loopback,
        .format_fw_ver  = (format_fw_ver_t)NULL,
        .hw_reset       = (hw_reset_t)NULL,
-       .set_link_led   = (set_link_led_t)NULL,
+       .set_link_led   = (set_link_led_t)bnx2x_5461x_set_link_led,
        .phy_specific_func = (phy_specific_func_t)NULL
 };
 /*****************************************************************/
index 6486ab8..2f6361e 100644 (file)
@@ -10548,33 +10548,38 @@ do {                                                                  \
 
 int bnx2x_init_firmware(struct bnx2x *bp)
 {
-       const char *fw_file_name;
        struct bnx2x_fw_file_hdr *fw_hdr;
        int rc;
 
-       if (CHIP_IS_E1(bp))
-               fw_file_name = FW_FILE_NAME_E1;
-       else if (CHIP_IS_E1H(bp))
-               fw_file_name = FW_FILE_NAME_E1H;
-       else if (!CHIP_IS_E1x(bp))
-               fw_file_name = FW_FILE_NAME_E2;
-       else {
-               BNX2X_ERR("Unsupported chip revision\n");
-               return -EINVAL;
-       }
 
-       BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
+       if (!bp->firmware) {
+               const char *fw_file_name;
 
-       rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev);
-       if (rc) {
-               BNX2X_ERR("Can't load firmware file %s\n", fw_file_name);
-               goto request_firmware_exit;
-       }
+               if (CHIP_IS_E1(bp))
+                       fw_file_name = FW_FILE_NAME_E1;
+               else if (CHIP_IS_E1H(bp))
+                       fw_file_name = FW_FILE_NAME_E1H;
+               else if (!CHIP_IS_E1x(bp))
+                       fw_file_name = FW_FILE_NAME_E2;
+               else {
+                       BNX2X_ERR("Unsupported chip revision\n");
+                       return -EINVAL;
+               }
+               BNX2X_DEV_INFO("Loading %s\n", fw_file_name);
 
-       rc = bnx2x_check_firmware(bp);
-       if (rc) {
-               BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
-               goto request_firmware_exit;
+               rc = request_firmware(&bp->firmware, fw_file_name,
+                                     &bp->pdev->dev);
+               if (rc) {
+                       BNX2X_ERR("Can't load firmware file %s\n",
+                                 fw_file_name);
+                       goto request_firmware_exit;
+               }
+
+               rc = bnx2x_check_firmware(bp);
+               if (rc) {
+                       BNX2X_ERR("Corrupt firmware file %s\n", fw_file_name);
+                       goto request_firmware_exit;
+               }
        }
 
        fw_hdr = (struct bnx2x_fw_file_hdr *)bp->firmware->data;
@@ -10630,6 +10635,7 @@ static void bnx2x_release_firmware(struct bnx2x *bp)
        kfree(bp->init_ops);
        kfree(bp->init_data);
        release_firmware(bp->firmware);
+       bp->firmware = NULL;
 }
 
 
@@ -10925,6 +10931,8 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
        if (bp->doorbells)
                iounmap(bp->doorbells);
 
+       bnx2x_release_firmware(bp);
+
        bnx2x_free_mem_bp(bp);
 
        free_netdev(dev);
index fc7bd0f..e58073e 100644 (file)
@@ -6990,6 +6990,7 @@ Theotherbitsarereservedandshouldbezero*/
 #define MDIO_REG_INTR_MASK                             0x1b
 #define MDIO_REG_INTR_MASK_LINK_STATUS                 (0x1 << 1)
 #define MDIO_REG_GPHY_SHADOW                           0x1c
+#define MDIO_REG_GPHY_SHADOW_LED_SEL1                  (0x0d << 10)
 #define MDIO_REG_GPHY_SHADOW_LED_SEL2                  (0x0e << 10)
 #define MDIO_REG_GPHY_SHADOW_WR_ENA                    (0x1 << 15)
 #define MDIO_REG_GPHY_SHADOW_AUTO_DET_MED              (0x1e << 10)
index 0440425..1451769 100644 (file)
@@ -5380,7 +5380,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp,
        rc = drv->init_fw(bp);
        if (rc) {
                BNX2X_ERR("Error loading firmware\n");
-               goto fw_init_err;
+               goto init_err;
        }
 
        /* Handle the beginning of COMMON_XXX pases separatelly... */
@@ -5388,25 +5388,25 @@ static int bnx2x_func_hw_init(struct bnx2x *bp,
        case FW_MSG_CODE_DRV_LOAD_COMMON_CHIP:
                rc = bnx2x_func_init_cmn_chip(bp, drv);
                if (rc)
-                       goto init_hw_err;
+                       goto init_err;
 
                break;
        case FW_MSG_CODE_DRV_LOAD_COMMON:
                rc = bnx2x_func_init_cmn(bp, drv);
                if (rc)
-                       goto init_hw_err;
+                       goto init_err;
 
                break;
        case FW_MSG_CODE_DRV_LOAD_PORT:
                rc = bnx2x_func_init_port(bp, drv);
                if (rc)
-                       goto init_hw_err;
+                       goto init_err;
 
                break;
        case FW_MSG_CODE_DRV_LOAD_FUNCTION:
                rc = bnx2x_func_init_func(bp, drv);
                if (rc)
-                       goto init_hw_err;
+                       goto init_err;
 
                break;
        default:
@@ -5414,10 +5414,7 @@ static int bnx2x_func_hw_init(struct bnx2x *bp,
                rc = -EINVAL;
        }
 
-init_hw_err:
-       drv->release_fw(bp);
-
-fw_init_err:
+init_err:
        drv->gunzip_end(bp);
 
        /* In case of success, complete the comand immediatelly: no ramrods
index 98849a1..b48378a 100644 (file)
@@ -7,6 +7,7 @@ config HAVE_NET_MACB
 
 config NET_ATMEL
        bool "Atmel devices"
+       default y
        depends on HAVE_NET_MACB || (ARM && ARCH_AT91RM9200)
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y.
index 438f458..2a22f52 100644 (file)
@@ -613,7 +613,7 @@ static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)
 
                if (!dm->wake_state)
                        irq_set_irq_wake(dm->irq_wake, 1);
-               else if (dm->wake_state & !opts)
+               else if (dm->wake_state && !opts)
                        irq_set_irq_wake(dm->irq_wake, 0);
        }
 
index c520cfd..5272f9d 100644 (file)
@@ -24,6 +24,7 @@ config FEC
        bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
        depends on (M523x || M527x || M5272 || M528x || M520x || M532x || \
                   ARCH_MXC || ARCH_MXS)
+       default ARCH_MXC || ARCH_MXS if ARM
        select PHYLIB
        ---help---
          Say Y here if you want to use the built-in 10/100 Fast ethernet
index 410d6a1..6650068 100644 (file)
@@ -61,9 +61,9 @@
 #ifdef EHEA_SMALL_QUEUES
 #define EHEA_MAX_CQE_COUNT      1023
 #define EHEA_DEF_ENTRIES_SQ     1023
-#define EHEA_DEF_ENTRIES_RQ1    4095
+#define EHEA_DEF_ENTRIES_RQ1    1023
 #define EHEA_DEF_ENTRIES_RQ2    1023
-#define EHEA_DEF_ENTRIES_RQ3    1023
+#define EHEA_DEF_ENTRIES_RQ3    511
 #else
 #define EHEA_MAX_CQE_COUNT      4080
 #define EHEA_DEF_ENTRIES_SQ     4080
index 37b70f7..bfeccbf 100644 (file)
@@ -371,7 +371,8 @@ static void ehea_update_stats(struct work_struct *work)
 out_herr:
        free_page((unsigned long)cb2);
 resched:
-       schedule_delayed_work(&port->stats_work, msecs_to_jiffies(1000));
+       schedule_delayed_work(&port->stats_work,
+                             round_jiffies_relative(msecs_to_jiffies(1000)));
 }
 
 static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
@@ -2434,7 +2435,8 @@ static int ehea_open(struct net_device *dev)
        }
 
        mutex_unlock(&port->port_lock);
-       schedule_delayed_work(&port->stats_work, msecs_to_jiffies(1000));
+       schedule_delayed_work(&port->stats_work,
+                             round_jiffies_relative(msecs_to_jiffies(1000)));
 
        return ret;
 }
index 4326681..acc31af 100644 (file)
@@ -1421,7 +1421,7 @@ static void veth_receive(struct veth_lpar_connection *cnx,
 
                /* FIXME: do we need this? */
                memset(local_list, 0, sizeof(local_list));
-               memset(remote_list, 0, sizeof(VETH_MAX_FRAMES_PER_MSG));
+               memset(remote_list, 0, sizeof(remote_list));
 
                /* a 0 address marks the end of the valid entries */
                if (senddata->addr[startchunk] == 0)
index 7becff1..76b8457 100644 (file)
@@ -1744,6 +1744,112 @@ jme_phy_off(struct jme_adapter *jme)
                jme_new_phy_off(jme);
 }
 
+static int
+jme_phy_specreg_read(struct jme_adapter *jme, u32 specreg)
+{
+       u32 phy_addr;
+
+       phy_addr = JM_PHY_SPEC_REG_READ | specreg;
+       jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+                       phy_addr);
+       return jme_mdio_read(jme->dev, jme->mii_if.phy_id,
+                       JM_PHY_SPEC_DATA_REG);
+}
+
+static void
+jme_phy_specreg_write(struct jme_adapter *jme, u32 ext_reg, u32 phy_data)
+{
+       u32 phy_addr;
+
+       phy_addr = JM_PHY_SPEC_REG_WRITE | ext_reg;
+       jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG,
+                       phy_data);
+       jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+                       phy_addr);
+}
+
+static int
+jme_phy_calibration(struct jme_adapter *jme)
+{
+       u32 ctrl1000, phy_data;
+
+       jme_phy_off(jme);
+       jme_phy_on(jme);
+       /*  Enabel PHY test mode 1 */
+       ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+       ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+       ctrl1000 |= PHY_GAD_TEST_MODE_1;
+       jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+
+       phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG);
+       phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0;
+       phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH |
+                       JM_PHY_EXT_COMM_2_CALI_ENABLE;
+       jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data);
+       msleep(20);
+       phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG);
+       phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE |
+                       JM_PHY_EXT_COMM_2_CALI_MODE_0 |
+                       JM_PHY_EXT_COMM_2_CALI_LATCH);
+       jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data);
+
+       /*  Disable PHY test mode */
+       ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+       ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+       jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+       return 0;
+}
+
+static int
+jme_phy_setEA(struct jme_adapter *jme)
+{
+       u32 phy_comm0 = 0, phy_comm1 = 0;
+       u8 nic_ctrl;
+
+       pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl);
+       if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE)
+               return 0;
+
+       switch (jme->pdev->device) {
+       case PCI_DEVICE_ID_JMICRON_JMC250:
+               if (((jme->chip_main_rev == 5) &&
+                       ((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+                       (jme->chip_sub_rev == 3))) ||
+                       (jme->chip_main_rev >= 6)) {
+                       phy_comm0 = 0x008A;
+                       phy_comm1 = 0x4109;
+               }
+               if ((jme->chip_main_rev == 3) &&
+                       ((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+                       phy_comm0 = 0xE088;
+               break;
+       case PCI_DEVICE_ID_JMICRON_JMC260:
+               if (((jme->chip_main_rev == 5) &&
+                       ((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+                       (jme->chip_sub_rev == 3))) ||
+                       (jme->chip_main_rev >= 6)) {
+                       phy_comm0 = 0x008A;
+                       phy_comm1 = 0x4109;
+               }
+               if ((jme->chip_main_rev == 3) &&
+                       ((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+                       phy_comm0 = 0xE088;
+               if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 0))
+                       phy_comm0 = 0x608A;
+               if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2))
+                       phy_comm0 = 0x408A;
+               break;
+       default:
+               return -ENODEV;
+       }
+       if (phy_comm0)
+               jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_0_REG, phy_comm0);
+       if (phy_comm1)
+               jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_1_REG, phy_comm1);
+
+       return 0;
+}
+
 static int
 jme_open(struct net_device *netdev)
 {
@@ -1769,7 +1875,8 @@ jme_open(struct net_device *netdev)
                jme_set_settings(netdev, &jme->old_ecmd);
        else
                jme_reset_phy_processor(jme);
-
+       jme_phy_calibration(jme);
+       jme_phy_setEA(jme);
        jme_reset_link(jme);
 
        return 0;
@@ -3184,7 +3291,8 @@ jme_resume(struct device *dev)
                jme_set_settings(netdev, &jme->old_ecmd);
        else
                jme_reset_phy_processor(jme);
-
+       jme_phy_calibration(jme);
+       jme_phy_setEA(jme);
        jme_start_irq(jme);
        netif_device_attach(netdev);
 
@@ -3239,4 +3347,3 @@ MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, jme_pci_tbl);
-
index 02ea27c..4304072 100644 (file)
@@ -760,6 +760,25 @@ enum jme_rxmcs_bits {
                                  RXMCS_CHECKSUM,
 };
 
+/*     Extern PHY common register 2    */
+
+#define PHY_GAD_TEST_MODE_1                    0x00002000
+#define PHY_GAD_TEST_MODE_MSK                  0x0000E000
+#define JM_PHY_SPEC_REG_READ                   0x00004000
+#define JM_PHY_SPEC_REG_WRITE                  0x00008000
+#define PHY_CALIBRATION_DELAY                  20
+#define JM_PHY_SPEC_ADDR_REG                   0x1E
+#define JM_PHY_SPEC_DATA_REG                   0x1F
+
+#define JM_PHY_EXT_COMM_0_REG                  0x30
+#define JM_PHY_EXT_COMM_1_REG                  0x31
+#define JM_PHY_EXT_COMM_2_REG                  0x32
+#define JM_PHY_EXT_COMM_2_CALI_ENABLE          0x01
+#define JM_PHY_EXT_COMM_2_CALI_MODE_0          0x02
+#define JM_PHY_EXT_COMM_2_CALI_LATCH           0x10
+#define PCI_PRIV_SHARE_NICCTRL                 0xF5
+#define JME_FLAG_PHYEA_ENABLE                  0x2
+
 /*
  * Wakeup Frame setup interface registers
  */
index 6bb2b95..0b3567a 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
 
 #include <asm/checksum.h>
 
index fdc6c39..7803efa 100644 (file)
@@ -50,7 +50,7 @@
 #include "sky2.h"
 
 #define DRV_NAME               "sky2"
-#define DRV_VERSION            "1.29"
+#define DRV_VERSION            "1.30"
 
 /*
  * The Yukon II chipset takes 64 bit command blocks (called list elements)
@@ -68,7 +68,7 @@
 #define MAX_SKB_TX_LE  (2 + (sizeof(dma_addr_t)/sizeof(u32))*(MAX_SKB_FRAGS+1))
 #define TX_MIN_PENDING         (MAX_SKB_TX_LE+1)
 #define TX_MAX_PENDING         1024
-#define TX_DEF_PENDING         127
+#define TX_DEF_PENDING         63
 
 #define TX_WATCHDOG            (5 * HZ)
 #define NAPI_WEIGHT            64
@@ -869,6 +869,7 @@ static void sky2_wol_init(struct sky2_port *sky2)
 
        /* block receiver */
        sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET);
+       sky2_read32(hw, B0_CTST);
 }
 
 static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
@@ -1274,6 +1275,14 @@ static void rx_set_checksum(struct sky2_port *sky2)
                     ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
 }
 
+/*
+ * Fixed initial key as seed to RSS.
+ */
+static const uint32_t rss_init_key[10] = {
+       0x7c3351da, 0x51c5cf4e, 0x44adbdd1, 0xe8d38d18, 0x48897c43,
+       0xb1d60e7e, 0x6a3dd760, 0x01a2e453, 0x16f46f13, 0x1a0e7b30
+};
+
 /* Enable/disable receive hash calculation (RSS) */
 static void rx_set_rss(struct net_device *dev, u32 features)
 {
@@ -1289,12 +1298,9 @@ static void rx_set_rss(struct net_device *dev, u32 features)
 
        /* Program RSS initial values */
        if (features & NETIF_F_RXHASH) {
-               u32 key[nkeys];
-
-               get_random_bytes(key, nkeys * sizeof(u32));
                for (i = 0; i < nkeys; i++)
                        sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4),
-                                    key[i]);
+                                    rss_init_key[i]);
 
                /* Need to turn on (undocumented) flag to make hashing work  */
                sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T),
@@ -1717,6 +1723,8 @@ static int sky2_setup_irq(struct sky2_hw *hw, const char *name)
        if (err)
                dev_err(&pdev->dev, "cannot assign irq %d\n", pdev->irq);
        else {
+               hw->flags |= SKY2_HW_IRQ_SETUP;
+
                napi_enable(&hw->napi);
                sky2_write32(hw, B0_IMSK, Y2_IS_BASE);
                sky2_read32(hw, B0_IMSK);
@@ -1727,7 +1735,7 @@ static int sky2_setup_irq(struct sky2_hw *hw, const char *name)
 
 
 /* Bring up network interface. */
-static int sky2_up(struct net_device *dev)
+static int sky2_open(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
@@ -1747,6 +1755,11 @@ static int sky2_up(struct net_device *dev)
 
        sky2_hw_up(sky2);
 
+       if (hw->chip_id == CHIP_ID_YUKON_OPT ||
+           hw->chip_id == CHIP_ID_YUKON_PRM ||
+           hw->chip_id == CHIP_ID_YUKON_OP_2)
+               imask |= Y2_IS_PHY_QLNK;        /* enable PHY Quick Link */
+
        /* Enable interrupts from phy/mac for port */
        imask = sky2_read32(hw, B0_IMSK);
        imask |= portirq_msk[port];
@@ -2040,6 +2053,8 @@ static void sky2_tx_reset(struct sky2_hw *hw, unsigned port)
 
        sky2_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET);
        sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET);
+
+       sky2_read32(hw, B0_CTST);
 }
 
 static void sky2_hw_down(struct sky2_port *sky2)
@@ -2090,7 +2105,7 @@ static void sky2_hw_down(struct sky2_port *sky2)
 }
 
 /* Network shutdown */
-static int sky2_down(struct net_device *dev)
+static int sky2_close(struct net_device *dev)
 {
        struct sky2_port *sky2 = netdev_priv(dev);
        struct sky2_hw *hw = sky2->hw;
@@ -2101,15 +2116,22 @@ static int sky2_down(struct net_device *dev)
 
        netif_info(sky2, ifdown, dev, "disabling interface\n");
 
-       /* Disable port IRQ */
-       sky2_write32(hw, B0_IMSK,
-                    sky2_read32(hw, B0_IMSK) & ~portirq_msk[sky2->port]);
-       sky2_read32(hw, B0_IMSK);
-
        if (hw->ports == 1) {
+               sky2_write32(hw, B0_IMSK, 0);
+               sky2_read32(hw, B0_IMSK);
+
                napi_disable(&hw->napi);
                free_irq(hw->pdev->irq, hw);
+               hw->flags &= ~SKY2_HW_IRQ_SETUP;
        } else {
+               u32 imask;
+
+               /* Disable port IRQ */
+               imask  = sky2_read32(hw, B0_IMSK);
+               imask &= ~portirq_msk[sky2->port];
+               sky2_write32(hw, B0_IMSK, imask);
+               sky2_read32(hw, B0_IMSK);
+
                synchronize_irq(hw->pdev->irq);
                napi_synchronize(&hw->napi);
        }
@@ -2587,7 +2609,7 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last)
        if (netif_running(dev)) {
                sky2_tx_complete(sky2, last);
 
-               /* Wake unless it's detached, and called e.g. from sky2_down() */
+               /* Wake unless it's detached, and called e.g. from sky2_close() */
                if (tx_avail(sky2) > MAX_SKB_TX_LE + 4)
                        netif_wake_queue(dev);
        }
@@ -3258,7 +3280,6 @@ static void sky2_reset(struct sky2_hw *hw)
            hw->chip_id == CHIP_ID_YUKON_PRM ||
            hw->chip_id == CHIP_ID_YUKON_OP_2) {
                u16 reg;
-               u32 msk;
 
                if (hw->chip_id == CHIP_ID_YUKON_OPT && hw->chip_rev == 0) {
                        /* disable PCI-E PHY power down (set PHY reg 0x80, bit 7 */
@@ -3281,11 +3302,6 @@ static void sky2_reset(struct sky2_hw *hw)
                sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON);
                sky2_pci_write16(hw, PSM_CONFIG_REG4, reg);
 
-               /* enable PHY Quick Link */
-               msk = sky2_read32(hw, B0_IMSK);
-               msk |= Y2_IS_PHY_QLNK;
-               sky2_write32(hw, B0_IMSK, msk);
-
                /* check if PSMv2 was running before */
                reg = sky2_pci_read16(hw, PSM_CONFIG_REG3);
                if (reg & PCI_EXP_LNKCTL_ASPMC)
@@ -3383,7 +3399,7 @@ static void sky2_detach(struct net_device *dev)
                netif_tx_lock(dev);
                netif_device_detach(dev);       /* stop txq */
                netif_tx_unlock(dev);
-               sky2_down(dev);
+               sky2_close(dev);
        }
 }
 
@@ -3393,7 +3409,7 @@ static int sky2_reattach(struct net_device *dev)
        int err = 0;
 
        if (netif_running(dev)) {
-               err = sky2_up(dev);
+               err = sky2_open(dev);
                if (err) {
                        netdev_info(dev, "could not restart %d\n", err);
                        dev_close(dev);
@@ -3410,10 +3426,13 @@ static void sky2_all_down(struct sky2_hw *hw)
 {
        int i;
 
-       sky2_read32(hw, B0_IMSK);
-       sky2_write32(hw, B0_IMSK, 0);
-       synchronize_irq(hw->pdev->irq);
-       napi_disable(&hw->napi);
+       if (hw->flags & SKY2_HW_IRQ_SETUP) {
+               sky2_read32(hw, B0_IMSK);
+               sky2_write32(hw, B0_IMSK, 0);
+
+               synchronize_irq(hw->pdev->irq);
+               napi_disable(&hw->napi);
+       }
 
        for (i = 0; i < hw->ports; i++) {
                struct net_device *dev = hw->dev[i];
@@ -3446,11 +3465,12 @@ static void sky2_all_up(struct sky2_hw *hw)
                netif_wake_queue(dev);
        }
 
-       sky2_write32(hw, B0_IMSK, imask);
-       sky2_read32(hw, B0_IMSK);
-
-       sky2_read32(hw, B0_Y2_SP_LISR);
-       napi_enable(&hw->napi);
+       if (hw->flags & SKY2_HW_IRQ_SETUP) {
+               sky2_write32(hw, B0_IMSK, imask);
+               sky2_read32(hw, B0_IMSK);
+               sky2_read32(hw, B0_Y2_SP_LISR);
+               napi_enable(&hw->napi);
+       }
 }
 
 static void sky2_restart(struct work_struct *work)
@@ -4071,6 +4091,16 @@ static int sky2_set_coalesce(struct net_device *dev,
        return 0;
 }
 
+/*
+ * Hardware is limited to min of 128 and max of 2048 for ring size
+ * and  rounded up to next power of two
+ * to avoid division in modulus calclation
+ */
+static unsigned long roundup_ring_size(unsigned long pending)
+{
+       return max(128ul, roundup_pow_of_two(pending+1));
+}
+
 static void sky2_get_ringparam(struct net_device *dev,
                               struct ethtool_ringparam *ering)
 {
@@ -4098,7 +4128,7 @@ static int sky2_set_ringparam(struct net_device *dev,
 
        sky2->rx_pending = ering->rx_pending;
        sky2->tx_pending = ering->tx_pending;
-       sky2->tx_ring_size = roundup_pow_of_two(sky2->tx_pending+1);
+       sky2->tx_ring_size = roundup_ring_size(sky2->tx_pending);
 
        return sky2_reattach(dev);
 }
@@ -4556,7 +4586,7 @@ static int sky2_device_event(struct notifier_block *unused,
        struct net_device *dev = ptr;
        struct sky2_port *sky2 = netdev_priv(dev);
 
-       if (dev->netdev_ops->ndo_open != sky2_up || !sky2_debug)
+       if (dev->netdev_ops->ndo_open != sky2_open || !sky2_debug)
                return NOTIFY_DONE;
 
        switch (event) {
@@ -4621,8 +4651,8 @@ static __exit void sky2_debug_cleanup(void)
    not allowing netpoll on second port */
 static const struct net_device_ops sky2_netdev_ops[2] = {
   {
-       .ndo_open               = sky2_up,
-       .ndo_stop               = sky2_down,
+       .ndo_open               = sky2_open,
+       .ndo_stop               = sky2_close,
        .ndo_start_xmit         = sky2_xmit_frame,
        .ndo_do_ioctl           = sky2_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
@@ -4638,8 +4668,8 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
 #endif
   },
   {
-       .ndo_open               = sky2_up,
-       .ndo_stop               = sky2_down,
+       .ndo_open               = sky2_open,
+       .ndo_stop               = sky2_close,
        .ndo_start_xmit         = sky2_xmit_frame,
        .ndo_do_ioctl           = sky2_ioctl,
        .ndo_validate_addr      = eth_validate_addr,
@@ -4692,7 +4722,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
        spin_lock_init(&sky2->phy_lock);
 
        sky2->tx_pending = TX_DEF_PENDING;
-       sky2->tx_ring_size = roundup_pow_of_two(TX_DEF_PENDING+1);
+       sky2->tx_ring_size = roundup_ring_size(TX_DEF_PENDING);
        sky2->rx_pending = RX_DEF_PENDING;
 
        hw->dev[port] = dev;
index 0af31b8..ff6f58b 100644 (file)
@@ -2287,6 +2287,7 @@ struct sky2_hw {
 #define SKY2_HW_RSS_BROKEN     0x00000100
 #define SKY2_HW_VLAN_BROKEN     0x00000200
 #define SKY2_HW_RSS_CHKSUM     0x00000400      /* RSS requires chksum */
+#define SKY2_HW_IRQ_SETUP      0x00000800
 
        u8                   chip_id;
        u8                   chip_rev;
index b89c36d..c2df6c3 100644 (file)
@@ -581,6 +581,7 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
                 * Packet is OK - process it.
                 */
                length = be32_to_cpu(cqe->byte_cnt);
+               length -= ring->fcs_del;
                ring->bytes += length;
                ring->packets++;
 
@@ -813,8 +814,11 @@ static int mlx4_en_config_rss_qp(struct mlx4_en_priv *priv, int qpn,
        context->db_rec_addr = cpu_to_be64(ring->wqres.db.dma);
 
        /* Cancel FCS removal if FW allows */
-       if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP)
+       if (mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_FCS_KEEP) {
                context->param3 |= cpu_to_be32(1 << 29);
+               ring->fcs_del = ETH_FCS_LEN;
+       } else
+               ring->fcs_del = 0;
 
        err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, context, qp, state);
        if (err) {
index 8fda331..207b5ad 100644 (file)
@@ -272,6 +272,7 @@ struct mlx4_en_rx_ring {
        u32 prod;
        u32 cons;
        u32 buf_size;
+       u8  fcs_del;
        void *buf;
        void *rx_info;
        unsigned long bytes;
index 1dca570..1c61d36 100644 (file)
@@ -609,7 +609,7 @@ struct nv_ethtool_str {
 };
 
 static const struct nv_ethtool_str nv_estats_str[] = {
-       { "tx_bytes" },
+       { "tx_bytes" }, /* includes Ethernet FCS CRC */
        { "tx_zero_rexmt" },
        { "tx_one_rexmt" },
        { "tx_many_rexmt" },
@@ -637,7 +637,7 @@ static const struct nv_ethtool_str nv_estats_str[] = {
        /* version 2 stats */
        { "tx_deferral" },
        { "tx_packets" },
-       { "rx_bytes" },
+       { "rx_bytes" }, /* includes Ethernet FCS CRC */
        { "tx_pause" },
        { "rx_pause" },
        { "rx_drop_frame" },
@@ -649,7 +649,7 @@ static const struct nv_ethtool_str nv_estats_str[] = {
 };
 
 struct nv_ethtool_stats {
-       u64 tx_bytes;
+       u64 tx_bytes; /* should be ifconfig->tx_bytes + 4*tx_packets */
        u64 tx_zero_rexmt;
        u64 tx_one_rexmt;
        u64 tx_many_rexmt;
@@ -670,14 +670,14 @@ struct nv_ethtool_stats {
        u64 rx_unicast;
        u64 rx_multicast;
        u64 rx_broadcast;
-       u64 rx_packets;
+       u64 rx_packets; /* should be ifconfig->rx_packets */
        u64 rx_errors_total;
        u64 tx_errors_total;
 
        /* version 2 stats */
        u64 tx_deferral;
-       u64 tx_packets;
-       u64 rx_bytes;
+       u64 tx_packets; /* should be ifconfig->tx_packets */
+       u64 rx_bytes;   /* should be ifconfig->rx_bytes + 4*rx_packets */
        u64 tx_pause;
        u64 rx_pause;
        u64 rx_drop_frame;
@@ -1706,10 +1706,17 @@ static struct net_device_stats *nv_get_stats(struct net_device *dev)
        if (np->driver_data & (DEV_HAS_STATISTICS_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_STATISTICS_V3)) {
                nv_get_hw_stats(dev);
 
+               /*
+                * Note: because HW stats are not always available and
+                * for consistency reasons, the following ifconfig
+                * stats are managed by software: rx_bytes, tx_bytes,
+                * rx_packets and tx_packets. The related hardware
+                * stats reported by ethtool should be equivalent to
+                * these ifconfig stats, with 4 additional bytes per
+                * packet (Ethernet FCS CRC).
+                */
+
                /* copy to net_device stats */
-               dev->stats.tx_packets = np->estats.tx_packets;
-               dev->stats.rx_bytes = np->estats.rx_bytes;
-               dev->stats.tx_bytes = np->estats.tx_bytes;
                dev->stats.tx_fifo_errors = np->estats.tx_fifo_errors;
                dev->stats.tx_carrier_errors = np->estats.tx_carrier_errors;
                dev->stats.rx_crc_errors = np->estats.rx_crc_errors;
@@ -2380,6 +2387,9 @@ static int nv_tx_done(struct net_device *dev, int limit)
                                if (flags & NV_TX_ERROR) {
                                        if ((flags & NV_TX_RETRYERROR) && !(flags & NV_TX_RETRYCOUNT_MASK))
                                                nv_legacybackoff_reseed(dev);
+                               } else {
+                                       dev->stats.tx_packets++;
+                                       dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
                                }
                                dev_kfree_skb_any(np->get_tx_ctx->skb);
                                np->get_tx_ctx->skb = NULL;
@@ -2390,6 +2400,9 @@ static int nv_tx_done(struct net_device *dev, int limit)
                                if (flags & NV_TX2_ERROR) {
                                        if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK))
                                                nv_legacybackoff_reseed(dev);
+                               } else {
+                                       dev->stats.tx_packets++;
+                                       dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
                                }
                                dev_kfree_skb_any(np->get_tx_ctx->skb);
                                np->get_tx_ctx->skb = NULL;
@@ -2429,6 +2442,9 @@ static int nv_tx_done_optimized(struct net_device *dev, int limit)
                                        else
                                                nv_legacybackoff_reseed(dev);
                                }
+                       } else {
+                               dev->stats.tx_packets++;
+                               dev->stats.tx_bytes += np->get_tx_ctx->skb->len;
                        }
 
                        dev_kfree_skb_any(np->get_tx_ctx->skb);
@@ -2678,6 +2694,7 @@ static int nv_rx_process(struct net_device *dev, int limit)
                skb->protocol = eth_type_trans(skb, dev);
                napi_gro_receive(&np->napi, skb);
                dev->stats.rx_packets++;
+               dev->stats.rx_bytes += len;
 next_pkt:
                if (unlikely(np->get_rx.orig++ == np->last_rx.orig))
                        np->get_rx.orig = np->first_rx.orig;
@@ -2761,6 +2778,7 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
                        }
                        napi_gro_receive(&np->napi, skb);
                        dev->stats.rx_packets++;
+                       dev->stats.rx_bytes += len;
                } else {
                        dev_kfree_skb(skb);
                }
index 9c075ea..9cb5f91 100644 (file)
@@ -18,8 +18,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  */
 
-#include <linux/module.h>      /* for __MODULE_STRING */
 #include "pch_gbe.h"
+#include <linux/module.h>      /* for __MODULE_STRING */
 
 #define OPTION_UNSET   -1
 #define OPTION_DISABLED 0
index 8731f79..b8478aa 100644 (file)
 
 
 #define TX_DESC_PER_IOCB 8
-/* The maximum number of frags we handle is based
- * on PAGE_SIZE...
- */
-#if (PAGE_SHIFT == 12) || (PAGE_SHIFT == 13)   /* 4k & 8k pages */
+
+#if ((MAX_SKB_FRAGS - TX_DESC_PER_IOCB) + 2) > 0
 #define TX_DESC_PER_OAL ((MAX_SKB_FRAGS - TX_DESC_PER_IOCB) + 2)
 #else /* all other page sizes */
 #define TX_DESC_PER_OAL 0
@@ -1353,7 +1351,7 @@ struct tx_ring_desc {
        struct ob_mac_iocb_req *queue_entry;
        u32 index;
        struct oal oal;
-       struct map_list map[MAX_SKB_FRAGS + 1];
+       struct map_list map[MAX_SKB_FRAGS + 2];
        int map_cnt;
        struct tx_ring_desc *next;
 };
index 1fc01ca..4bf68cf 100644 (file)
@@ -940,7 +940,7 @@ static void r6040_multicast_list(struct net_device *dev)
        iowrite16(lp->mcr0, ioaddr + MCR0);
 
        /* Fill the MAC hash tables with their values */
-       if (lp->mcr0 && MCR0_HASH_EN) {
+       if (lp->mcr0 & MCR0_HASH_EN) {
                iowrite16(hash_table[0], ioaddr + MAR0);
                iowrite16(hash_table[1], ioaddr + MAR1);
                iowrite16(hash_table[2], ioaddr + MAR2);
index 92b45f0..6f06aa1 100644 (file)
@@ -1292,7 +1292,7 @@ static void __rtl8169_check_link_status(struct net_device *dev,
                netif_carrier_off(dev);
                netif_info(tp, ifdown, dev, "link down\n");
                if (pm)
-                       pm_schedule_suspend(&tp->pci_dev->dev, 100);
+                       pm_schedule_suspend(&tp->pci_dev->dev, 5000);
        }
        spin_unlock_irqrestore(&tp->lock, flags);
 }
index d2be42a..8843071 100644 (file)
@@ -1937,6 +1937,7 @@ static int __devinit smsc911x_init(struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
        unsigned int byte_test;
+       unsigned int to = 100;
 
        SMSC_TRACE(pdata, probe, "Driver Parameters:");
        SMSC_TRACE(pdata, probe, "LAN base: 0x%08lX",
@@ -1952,6 +1953,17 @@ static int __devinit smsc911x_init(struct net_device *dev)
                return -ENODEV;
        }
 
+       /*
+        * poll the READY bit in PMT_CTRL. Any other access to the device is
+        * forbidden while this bit isn't set. Try for 100ms
+        */
+       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+               udelay(1000);
+       if (to == 0) {
+               pr_err("Device not READY in 100ms aborting\n");
+               return -ENODEV;
+       }
+
        /* Check byte ordering */
        byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
        SMSC_TRACE(pdata, probe, "BYTE_TEST: 0x%08X", byte_test);
index da66ac5..4d5402a 100644 (file)
@@ -39,10 +39,11 @@ static int dwmac1000_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
        /* DMA SW reset */
        value |= DMA_BUS_MODE_SFT_RESET;
        writel(value, ioaddr + DMA_BUS_MODE);
-       limit = 15000;
+       limit = 10;
        while (limit--) {
                if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
                        break;
+               mdelay(10);
        }
        if (limit < 0)
                return -EBUSY;
index 627f656..bc17fd0 100644 (file)
@@ -41,10 +41,11 @@ static int dwmac100_dma_init(void __iomem *ioaddr, int pbl, u32 dma_tx,
        /* DMA SW reset */
        value |= DMA_BUS_MODE_SFT_RESET;
        writel(value, ioaddr + DMA_BUS_MODE);
-       limit = 15000;
+       limit = 10;
        while (limit--) {
                if (!(readl(ioaddr + DMA_BUS_MODE) & DMA_BUS_MODE_SFT_RESET))
                        break;
+               mdelay(10);
        }
        if (limit < 0)
                return -EBUSY;
index 9bafa6c..a140a8f 100644 (file)
@@ -72,7 +72,6 @@ struct stmmac_priv {
        spinlock_t lock;
        spinlock_t tx_lock;
        int wolopts;
-       int wolenabled;
        int wol_irq;
 #ifdef CONFIG_STMMAC_TIMER
        struct stmmac_timer *tm;
@@ -80,6 +79,7 @@ struct stmmac_priv {
        struct plat_stmmacenet_data *plat;
        struct stmmac_counters mmc;
        struct dma_features dma_cap;
+       int hw_cap_support;
 };
 
 extern int stmmac_mdio_unregister(struct net_device *ndev);
index e8eff09..0395f9e 100644 (file)
@@ -430,6 +430,12 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
        struct stmmac_priv *priv = netdev_priv(dev);
        u32 support = WAKE_MAGIC | WAKE_UCAST;
 
+       /* By default almost all GMAC devices support the WoL via
+        * magic frame but we can disable it if the HW capability
+        * register shows no support for pmt_magic_frame. */
+       if ((priv->hw_cap_support) && (!priv->dma_cap.pmt_magic_frame))
+               wol->wolopts &= ~WAKE_MAGIC;
+
        if (!device_can_wakeup(priv->device))
                return -EINVAL;
 
index 20546bb..72cd190 100644 (file)
@@ -321,12 +321,10 @@ static int stmmac_init_phy(struct net_device *dev)
        }
 
        /* Stop Advertising 1000BASE Capability if interface is not GMII */
-       if ((interface) && ((interface == PHY_INTERFACE_MODE_MII) ||
-           (interface == PHY_INTERFACE_MODE_RMII))) {
-               phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
-                                     SUPPORTED_Asym_Pause);
-               phydev->advertising = phydev->supported;
-       }
+       if ((interface == PHY_INTERFACE_MODE_MII) ||
+           (interface == PHY_INTERFACE_MODE_RMII))
+               phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
+                                        SUPPORTED_1000baseT_Full);
 
        /*
         * Broken HW is sometimes missing the pull-up resistor on the
@@ -783,10 +781,15 @@ static void stmmac_mmc_setup(struct stmmac_priv *priv)
        unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
                            MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
 
-       /* Do not manage MMC IRQ (FIXME) */
+       /* Mask MMC irq, counters are managed in SW and registers
+        * are cleared on each READ eventually. */
        dwmac_mmc_intr_all_mask(priv->ioaddr);
-       dwmac_mmc_ctrl(priv->ioaddr, mode);
-       memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
+
+       if (priv->dma_cap.rmon) {
+               dwmac_mmc_ctrl(priv->ioaddr, mode);
+               memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
+       } else
+               pr_info(" No MAC Management Counters available");
 }
 
 static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
@@ -807,8 +810,29 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
        return 0;
 }
 
-/* New GMAC chips support a new register to indicate the
- * presence of the optional feature/functions.
+/**
+ * stmmac_selec_desc_mode
+ * @dev : device pointer
+ * Description: select the Enhanced/Alternate or Normal descriptors */
+static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
+{
+       if (priv->plat->enh_desc) {
+               pr_info(" Enhanced/Alternate descriptors\n");
+               priv->hw->desc = &enh_desc_ops;
+       } else {
+               pr_info(" Normal descriptors\n");
+               priv->hw->desc = &ndesc_ops;
+       }
+}
+
+/**
+ * stmmac_get_hw_features
+ * @priv : private device pointer
+ * Description:
+ *  new GMAC chip generations have a new register to indicate the
+ *  presence of the optional feature/functions.
+ *  This can be also used to override the value passed through the
+ *  platform and necessary for old MAC10/100 and GMAC chips.
  */
 static int stmmac_get_hw_features(struct stmmac_priv *priv)
 {
@@ -829,7 +853,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
                        (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
                priv->dma_cap.pmt_magic_frame =
                        (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
-               /*MMC*/
+               /* MMC */
                priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
                /* IEEE 1588-2002*/
                priv->dma_cap.time_stamp =
@@ -857,8 +881,7 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)
                priv->dma_cap.enh_desc =
                        (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
 
-       } else
-               pr_debug("\tNo HW DMA feature register supported");
+       }
 
        return hw_cap;
 }
@@ -913,6 +936,44 @@ static int stmmac_open(struct net_device *dev)
                goto open_error;
        }
 
+       stmmac_get_synopsys_id(priv);
+
+       priv->hw_cap_support = stmmac_get_hw_features(priv);
+
+       if (priv->hw_cap_support) {
+               pr_info(" Support DMA HW capability register");
+
+               /* We can override some gmac/dma configuration fields: e.g.
+                * enh_desc, tx_coe (e.g. that are passed through the
+                * platform) with the values from the HW capability
+                * register (if supported).
+                */
+               priv->plat->enh_desc = priv->dma_cap.enh_desc;
+               priv->plat->tx_coe = priv->dma_cap.tx_coe;
+               priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
+
+               /* By default disable wol on magic frame if not supported */
+               if (!priv->dma_cap.pmt_magic_frame)
+                       priv->wolopts &= ~WAKE_MAGIC;
+
+       } else
+               pr_info(" No HW DMA feature register supported");
+
+       /* Select the enhnaced/normal descriptor structures */
+       stmmac_selec_desc_mode(priv);
+
+       /* PMT module is not integrated in all the MAC devices. */
+       if (priv->plat->pmt) {
+               pr_info(" Remote wake-up capable\n");
+               device_set_wakeup_capable(priv->device, 1);
+       }
+
+       priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
+       if (priv->rx_coe)
+               pr_info(" Checksum Offload Engine supported\n");
+       if (priv->plat->tx_coe)
+               pr_info(" Checksum insertion supported\n");
+
        /* Create and initialize the TX/RX descriptors chains. */
        priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
        priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
@@ -935,15 +996,6 @@ static int stmmac_open(struct net_device *dev)
        /* Initialize the MAC Core */
        priv->hw->mac->core_init(priv->ioaddr);
 
-       stmmac_get_synopsys_id(priv);
-
-       stmmac_get_hw_features(priv);
-
-       priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr);
-       if (priv->rx_coe)
-               pr_info("stmmac: Rx Checksum Offload Engine supported\n");
-       if (priv->plat->tx_coe)
-               pr_info("\tTX Checksum insertion supported\n");
        netdev_update_features(dev);
 
        /* Request the IRQ lines */
@@ -965,8 +1017,7 @@ static int stmmac_open(struct net_device *dev)
        memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
        priv->xstats.threshold = tc;
 
-       if (priv->dma_cap.rmon)
-               stmmac_mmc_setup(priv);
+       stmmac_mmc_setup(priv);
 
        /* Start the ball rolling... */
        DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name);
@@ -1489,9 +1540,7 @@ static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        if (!priv->phydev)
                return -EINVAL;
 
-       spin_lock(&priv->lock);
        ret = phy_mii_ioctl(priv->phydev, rq, cmd);
-       spin_unlock(&priv->lock);
 
        return ret;
 }
@@ -1558,7 +1607,7 @@ static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
        struct net_device *dev = seq->private;
        struct stmmac_priv *priv = netdev_priv(dev);
 
-       if (!stmmac_get_hw_features(priv)) {
+       if (!priv->hw_cap_support) {
                seq_printf(seq, "DMA HW features not supported\n");
                return 0;
        }
@@ -1766,12 +1815,6 @@ static int stmmac_mac_device_setup(struct net_device *dev)
        if (!device)
                return -ENOMEM;
 
-       if (priv->plat->enh_desc) {
-               device->desc = &enh_desc_ops;
-               pr_info("\tEnhanced descriptor structure\n");
-       } else
-               device->desc = &ndesc_ops;
-
        priv->hw = device;
        priv->hw->ring = &ring_mode_ops;
 
@@ -1845,11 +1888,6 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
 
        priv->ioaddr = addr;
 
-       /* PMT module is not integrated in all the MAC devices. */
-       if (plat_dat->pmt) {
-               pr_info("\tPMT module supported\n");
-               device_set_wakeup_capable(&pdev->dev, 1);
-       }
        /*
         * On some platforms e.g. SPEAr the wake up irq differs from the mac irq
         * The external wake up irq can be passed through the platform code
@@ -1862,7 +1900,6 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
        if (priv->wol_irq == -ENXIO)
                priv->wol_irq = ndev->irq;
 
-
        platform_set_drvdata(pdev, ndev);
 
        /* Set the I/O base addr */
@@ -1875,7 +1912,7 @@ static int stmmac_dvr_probe(struct platform_device *pdev)
                        goto out_free_ndev;
        }
 
-       /* MAC HW revice detection */
+       /* MAC HW device detection */
        ret = stmmac_mac_device_setup(ndev);
        if (ret < 0)
                goto out_plat_exit;
@@ -1978,12 +2015,13 @@ static int stmmac_suspend(struct device *dev)
        if (!ndev || !netif_running(ndev))
                return 0;
 
+       if (priv->phydev)
+               phy_stop(priv->phydev);
+
        spin_lock(&priv->lock);
 
        netif_device_detach(ndev);
        netif_stop_queue(ndev);
-       if (priv->phydev)
-               phy_stop(priv->phydev);
 
 #ifdef CONFIG_STMMAC_TIMER
        priv->tm->timer_stop();
@@ -2041,12 +2079,13 @@ static int stmmac_resume(struct device *dev)
 #endif
        napi_enable(&priv->napi);
 
-       if (priv->phydev)
-               phy_start(priv->phydev);
-
        netif_start_queue(ndev);
 
        spin_unlock(&priv->lock);
+
+       if (priv->phydev)
+               phy_start(priv->phydev);
+
        return 0;
 }
 
index c517dac..cf14ab9 100644 (file)
@@ -2637,7 +2637,7 @@ static int __devinit happy_meal_sbus_probe_one(struct platform_device *op, int i
        sbus_dp = op->dev.parent->of_node;
 
        /* We can match PCI devices too, do not accept those here. */
-       if (strcmp(sbus_dp->name, "sbus"))
+       if (strcmp(sbus_dp->name, "sbus") && strcmp(sbus_dp->name, "sbi"))
                return err;
 
        if (is_qfe) {
index caf3659..2681b53 100644 (file)
@@ -114,6 +114,7 @@ void temac_indirect_out32(struct temac_local *lp, int reg, u32 value)
                return;
        temac_iow(lp, XTE_LSW0_OFFSET, value);
        temac_iow(lp, XTE_CTL0_OFFSET, CNTLREG_WRITE_ENABLE_MASK | reg);
+       temac_indirect_busywait(lp);
 }
 
 /**
@@ -203,6 +204,9 @@ static void temac_dma_bd_release(struct net_device *ndev)
        struct temac_local *lp = netdev_priv(ndev);
        int i;
 
+       /* Reset Local Link (DMA) */
+       lp->dma_out(lp, DMA_CONTROL_REG, DMA_CONTROL_RST);
+
        for (i = 0; i < RX_BD_NUM; i++) {
                if (!lp->rx_skb[i])
                        break;
@@ -860,6 +864,8 @@ static int temac_open(struct net_device *ndev)
                phy_start(lp->phy_dev);
        }
 
+       temac_device_reset(ndev);
+
        rc = request_irq(lp->tx_irq, ll_temac_tx_irq, 0, ndev->name, ndev);
        if (rc)
                goto err_tx_irq;
@@ -867,7 +873,6 @@ static int temac_open(struct net_device *ndev)
        if (rc)
                goto err_rx_irq;
 
-       temac_device_reset(ndev);
        return 0;
 
  err_rx_irq:
index 7393eb7..95eb34f 100644 (file)
@@ -36,4 +36,4 @@ config ROADRUNNER_LARGE_RINGS
          kernel code or by user space programs. Say Y here only if you have
          the memory.
 
-endif /* HIPPI */
+endif # HIPPI
index bb88e12..a702443 100644 (file)
@@ -3,7 +3,7 @@
 #
 
 menuconfig PHYLIB
-       bool "PHY Device support and infrastructure"
+       tristate "PHY Device support and infrastructure"
        depends on !S390
        depends on NETDEVICES
        help
index e81e22e..e6fed4d 100644 (file)
@@ -36,7 +36,7 @@
 #include <linux/usb/usbnet.h>
 #include <linux/slab.h>
 
-#define DRIVER_VERSION "26-Sep-2011"
+#define DRIVER_VERSION "08-Nov-2011"
 #define DRIVER_NAME "asix"
 
 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
 #define MARVELL_CTRL_TXDELAY   0x0002
 #define MARVELL_CTRL_RXDELAY   0x0080
 
-#define        PHY_MODE_RTL8211CL      0x0004
+#define        PHY_MODE_RTL8211CL      0x000C
 
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct asix_data {
@@ -652,9 +652,17 @@ static u32 asix_get_phyid(struct usbnet *dev)
 {
        int phy_reg;
        u32 phy_id;
+       int i;
 
-       phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
-       if (phy_reg < 0)
+       /* Poll for the rare case the FW or phy isn't ready yet.  */
+       for (i = 0; i < 100; i++) {
+               phy_reg = asix_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1);
+               if (phy_reg != 0 && phy_reg != 0xFFFF)
+                       break;
+               mdelay(1);
+       }
+
+       if (phy_reg <= 0 || phy_reg == 0xFFFF)
                return 0;
 
        phy_id = (phy_reg & 0xffff) << 16;
@@ -1075,7 +1083,7 @@ static const struct net_device_ops ax88772_netdev_ops = {
 
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-       int ret;
+       int ret, embd_phy;
        struct asix_data *data = (struct asix_data *)&dev->data;
        u8 buf[ETH_ALEN];
        u32 phyid;
@@ -1100,16 +1108,36 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->mii.reg_num_mask = 0x1f;
        dev->mii.phy_id = asix_get_phy_addr(dev);
 
-       phyid = asix_get_phyid(dev);
-       dbg("PHYID=0x%08x", phyid);
-
        dev->net->netdev_ops = &ax88772_netdev_ops;
        dev->net->ethtool_ops = &ax88772_ethtool_ops;
 
-       ret = ax88772_reset(dev);
+       embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
+
+       /* Reset the PHY to normal operation mode */
+       ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL);
+       if (ret < 0) {
+               dbg("Select PHY #1 failed: %d", ret);
+               return ret;
+       }
+
+       ret = asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL);
+       if (ret < 0)
+               return ret;
+
+       msleep(150);
+
+       ret = asix_sw_reset(dev, AX_SWRESET_CLEAR);
        if (ret < 0)
                return ret;
 
+       msleep(150);
+
+       ret = asix_sw_reset(dev, embd_phy ? AX_SWRESET_IPRL : AX_SWRESET_PRTE);
+
+       /* Read PHYID register *AFTER* the PHY was reset properly */
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
+
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
        if (dev->driver_info->flags & FLAG_FRAMING_AX) {
                /* hard_mtu  is still the default - the device does not support
@@ -1220,6 +1248,7 @@ static int ax88178_reset(struct usbnet *dev)
        __le16 eeprom;
        u8 status;
        int gpio0 = 0;
+       u32 phyid;
 
        asix_read_cmd(dev, AX_CMD_READ_GPIOS, 0, 0, 1, &status);
        dbg("GPIO Status: 0x%04x", status);
@@ -1235,12 +1264,13 @@ static int ax88178_reset(struct usbnet *dev)
                data->ledmode = 0;
                gpio0 = 1;
        } else {
-               data->phymode = le16_to_cpu(eeprom) & 7;
+               data->phymode = le16_to_cpu(eeprom) & 0x7F;
                data->ledmode = le16_to_cpu(eeprom) >> 8;
                gpio0 = (le16_to_cpu(eeprom) & 0x80) ? 0 : 1;
        }
        dbg("GPIO0: %d, PhyMode: %d", gpio0, data->phymode);
 
+       /* Power up external GigaPHY through AX88178 GPIO pin */
        asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_1 | AX_GPIO_GPO1EN, 40);
        if ((le16_to_cpu(eeprom) >> 8) != 1) {
                asix_write_gpio(dev, 0x003c, 30);
@@ -1252,6 +1282,13 @@ static int ax88178_reset(struct usbnet *dev)
                asix_write_gpio(dev, AX_GPIO_GPO1EN | AX_GPIO_GPO_1, 30);
        }
 
+       /* Read PHYID register *AFTER* powering up PHY */
+       phyid = asix_get_phyid(dev);
+       dbg("PHYID=0x%08x", phyid);
+
+       /* Set AX88178 to enable MII/GMII/RGMII interface for external PHY */
+       asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0, 0, 0, NULL);
+
        asix_sw_reset(dev, 0);
        msleep(150);
 
@@ -1396,7 +1433,6 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        int ret;
        u8 buf[ETH_ALEN];
-       u32 phyid;
        struct asix_data *data = (struct asix_data *)&dev->data;
 
        data->eeprom_len = AX88772_EEPROM_LEN;
@@ -1423,12 +1459,12 @@ static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->netdev_ops = &ax88178_netdev_ops;
        dev->net->ethtool_ops = &ax88178_ethtool_ops;
 
-       phyid = asix_get_phyid(dev);
-       dbg("PHYID=0x%08x", phyid);
+       /* Blink LEDS so users know driver saw dongle */
+       asix_sw_reset(dev, 0);
+       msleep(150);
 
-       ret = ax88178_reset(dev);
-       if (ret < 0)
-               return ret;
+       asix_sw_reset(dev, AX_SWRESET_PRL | AX_SWRESET_IPPD);
+       msleep(150);
 
        /* Asix framing packs multiple eth frames into a 2K usb bulk transfer */
        if (dev->driver_info->flags & FLAG_FRAMING_AX) {
index c924ea2..99ed6eb 100644 (file)
@@ -567,7 +567,7 @@ static const struct usb_device_id   products [] = {
 {
        USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
-       .driver_info = (unsigned long)&wwan_info,
+       .driver_info = 0,
 },
 
 /*
index d43db32..9c26c63 100644 (file)
@@ -144,10 +144,11 @@ static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        }
 
        frame = (struct vl600_frame_hdr *) buf->data;
-       /* NOTE: Should check that frame->magic == 0x53544448?
-        * Otherwise if we receive garbage at the beginning of the frame
-        * we may end up allocating a huge buffer and saving all the
-        * future incoming data into it.  */
+       /* Yes, check that frame->magic == 0x53544448 (or 0x44544d48),
+        * otherwise we may run out of memory w/a bad packet */
+       if (ntohl(frame->magic) != 0x53544448 &&
+                       ntohl(frame->magic) != 0x44544d48)
+               goto error;
 
        if (buf->len < sizeof(*frame) ||
                        buf->len != le32_to_cpup(&frame->len)) {
@@ -296,6 +297,11 @@ encapsulate:
         * overwrite the remaining fields.
         */
        packet = (struct vl600_pkt_hdr *) skb->data;
+       /* The VL600 wants IPv6 packets to have an IPv4 ethertype
+        * Since this modem only supports IPv4 and IPv6, just set all
+        * frames to 0x0800 (ETH_P_IP)
+        */
+       packet->h_proto = htons(ETH_P_IP);
        memset(&packet->dummy, 0, sizeof(packet->dummy));
        packet->len = cpu_to_le32(orig_len);
 
@@ -308,21 +314,12 @@ encapsulate:
        if (skb->len < full_len) /* Pad */
                skb_put(skb, full_len - skb->len);
 
-       /* The VL600 wants IPv6 packets to have an IPv4 ethertype
-        * Check if this is an IPv6 packet, and set the ethertype
-        * to 0x800
-        */
-       if ((skb->data[sizeof(struct vl600_pkt_hdr *) + 0x22] & 0xf0) == 0x60) {
-               skb->data[sizeof(struct vl600_pkt_hdr *) + 0x20] = 0x08;
-               skb->data[sizeof(struct vl600_pkt_hdr *) + 0x21] = 0;
-       }
-
        return skb;
 }
 
 static const struct driver_info        vl600_info = {
        .description    = "LG VL600 modem",
-       .flags          = FLAG_ETHER | FLAG_RX_ASSEMBLE,
+       .flags          = FLAG_RX_ASSEMBLE | FLAG_WWAN,
        .bind           = vl600_bind,
        .unbind         = vl600_unbind,
        .status         = usbnet_cdc_status,
index 22a7cf9..a5b9b12 100644 (file)
@@ -51,6 +51,7 @@
 #define USB_VENDOR_ID_SMSC             (0x0424)
 #define USB_PRODUCT_ID_LAN7500         (0x7500)
 #define USB_PRODUCT_ID_LAN7505         (0x7505)
+#define RXW_PADDING                    2
 
 #define check_warn(ret, fmt, args...) \
        ({ if (ret < 0) netdev_warn(dev->net, fmt, ##args); })
@@ -1088,13 +1089,13 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 
                memcpy(&rx_cmd_b, skb->data, sizeof(rx_cmd_b));
                le32_to_cpus(&rx_cmd_b);
-               skb_pull(skb, 4 + NET_IP_ALIGN);
+               skb_pull(skb, 4 + RXW_PADDING);
 
                packet = skb->data;
 
                /* get the packet length */
-               size = (rx_cmd_a & RX_CMD_A_LEN) - NET_IP_ALIGN;
-               align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4;
+               size = (rx_cmd_a & RX_CMD_A_LEN) - RXW_PADDING;
+               align_count = (4 - ((size + RXW_PADDING) % 4)) % 4;
 
                if (unlikely(rx_cmd_a & RX_CMD_A_RED)) {
                        netif_dbg(dev, rx_err, dev->net,
index 2f91acc..8873c6e 100644 (file)
@@ -1827,7 +1827,8 @@ static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip)
        }
 
        /* Clear Bit 14 of AR_WA after putting chip into Full Sleep mode. */
-       REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
+       if (AR_SREV_9300_20_OR_LATER(ah))
+               REG_WRITE(ah, AR_WA, ah->WARegVal & ~AR_WA_D3_L1_DISABLE);
 }
 
 /*
index 85fa9cc..65ecb5b 100644 (file)
@@ -254,6 +254,8 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
        int r;
 
        sband = wiphy->bands[IEEE80211_BAND_2GHZ];
+       if (!sband)
+               return;
 
        /*
         * If no country IE has been received always enable active scan
index 58ea0e5..5f77cbe 100644 (file)
@@ -175,6 +175,7 @@ void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp,
        }
 }
 
+/* TODO: verify if needed for SSLPN or LCN  */
 static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
 {
        const struct b43_phy *phy = &dev->phy;
@@ -256,6 +257,9 @@ int b43_generate_txhdr(struct b43_wldev *dev,
        unsigned int plcp_fragment_len;
        u32 mac_ctl = 0;
        u16 phy_ctl = 0;
+       bool fill_phy_ctl1 = (phy->type == B43_PHYTYPE_LP ||
+                             phy->type == B43_PHYTYPE_N ||
+                             phy->type == B43_PHYTYPE_HT);
        u8 extra_ft = 0;
        struct ieee80211_rate *txrate;
        struct ieee80211_tx_rate *rates;
@@ -531,7 +535,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
                        extra_ft |= B43_TXH_EFT_RTSFB_CCK;
 
                if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
-                   phy->type == B43_PHYTYPE_N) {
+                   fill_phy_ctl1) {
                        txhdr->phy_ctl1_rts = cpu_to_le16(
                                b43_generate_tx_phy_ctl1(dev, rts_rate));
                        txhdr->phy_ctl1_rts_fb = cpu_to_le16(
@@ -552,7 +556,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
                break;
        }
 
-       if (phy->type == B43_PHYTYPE_N) {
+       if (fill_phy_ctl1) {
                txhdr->phy_ctl1 =
                        cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
                txhdr->phy_ctl1_fb =
@@ -736,7 +740,14 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
 
        /* Link quality statistics */
        switch (chanstat & B43_RX_CHAN_PHYTYPE) {
+       case B43_PHYTYPE_HT:
+               /* TODO: is max the right choice? */
+               status.signal = max_t(__s8,
+                       max(rxhdr->phy_ht_power0, rxhdr->phy_ht_power1),
+                       rxhdr->phy_ht_power2);
+               break;
        case B43_PHYTYPE_N:
+               /* Broadcom has code for min and avg, but always uses max */
                if (rxhdr->power0 == 16 || rxhdr->power0 == 32)
                        status.signal = max(rxhdr->power1, rxhdr->power2);
                else
index 16c514d..98d9074 100644 (file)
@@ -249,6 +249,12 @@ struct b43_rxhdr_fw4 {
                } __packed;
        } __packed;
        union {
+               /* HT-PHY */
+               struct {
+                       PAD_BYTES(1);
+                       __s8 phy_ht_power0;
+               } __packed;
+
                /* RSSI for N-PHYs */
                struct {
                        __s8 power2;
@@ -257,7 +263,15 @@ struct b43_rxhdr_fw4 {
 
                __le16 phy_status2;     /* PHY RX Status 2 */
        } __packed;
-       __le16 phy_status3;     /* PHY RX Status 3 */
+       union {
+               /* HT-PHY */
+               struct {
+                       __s8 phy_ht_power1;
+                       __s8 phy_ht_power2;
+               } __packed;
+
+               __le16 phy_status3;     /* PHY RX Status 3 */
+       } __packed;
        union {
                /* Tested with 598.314, 644.1001 and 666.2 */
                struct {
index b56a302..6ebec8f 100644 (file)
@@ -358,13 +358,14 @@ static uint nrxdactive(struct dma_info *di, uint h, uint t)
 
 static uint _dma_ctrlflags(struct dma_info *di, uint mask, uint flags)
 {
-       uint dmactrlflags = di->dma.dmactrlflags;
+       uint dmactrlflags;
 
        if (di == NULL) {
-               DMA_ERROR(("%s: _dma_ctrlflags: NULL dma handle\n", di->name));
+               DMA_ERROR(("_dma_ctrlflags: NULL dma handle\n"));
                return 0;
        }
 
+       dmactrlflags = di->dma.dmactrlflags;
        dmactrlflags &= ~mask;
        dmactrlflags |= flags;
 
index da34110..ce91898 100644 (file)
@@ -990,29 +990,16 @@ static int iwl_trans_tx_stop(struct iwl_trans *trans)
        return 0;
 }
 
-static void iwl_trans_pcie_disable_sync_irq(struct iwl_trans *trans)
+static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 {
        unsigned long flags;
-       struct iwl_trans_pcie *trans_pcie =
-               IWL_TRANS_GET_PCIE_TRANS(trans);
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
+       /* tell the device to stop sending interrupts */
        spin_lock_irqsave(&trans->shrd->lock, flags);
        iwl_disable_interrupts(trans);
        spin_unlock_irqrestore(&trans->shrd->lock, flags);
 
-       /* wait to make sure we flush pending tasklet*/
-       synchronize_irq(bus(trans)->irq);
-       tasklet_kill(&trans_pcie->irq_tasklet);
-}
-
-static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
-{
-       /* stop and reset the on-board processor */
-       iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-       /* tell the device to stop sending interrupts */
-       iwl_trans_pcie_disable_sync_irq(trans);
-
        /* device going down, Stop using ICT table */
        iwl_disable_ict(trans);
 
@@ -1039,6 +1026,20 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
 
        /* Stop the device, and put it in low power state */
        iwl_apm_stop(priv(trans));
+
+       /* Upon stop, the APM issues an interrupt if HW RF kill is set.
+        * Clean again the interrupt here
+        */
+       spin_lock_irqsave(&trans->shrd->lock, flags);
+       iwl_disable_interrupts(trans);
+       spin_unlock_irqrestore(&trans->shrd->lock, flags);
+
+       /* wait to make sure we flush pending tasklet*/
+       synchronize_irq(bus(trans)->irq);
+       tasklet_kill(&trans_pcie->irq_tasklet);
+
+       /* stop and reset the on-board processor */
+       iwl_write32(bus(trans), CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
 }
 
 static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
index 4fcd653..a7f1ab2 100644 (file)
@@ -634,7 +634,7 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy,
                        if (channel &&
                            !(channel->flags & IEEE80211_CHAN_DISABLED))
                                cfg80211_inform_bss(wiphy, channel,
-                                       bssid, le64_to_cpu(*(__le64 *)tsfdesc),
+                                       bssid, get_unaligned_le64(tsfdesc),
                                        capa, intvl, ie, ielen,
                                        LBS_SCAN_RSSI_TO_MBM(rssi),
                                        GFP_KERNEL);
index 11b69b3..728baa4 100644 (file)
@@ -995,6 +995,7 @@ static int if_spi_host_to_card(struct lbs_private *priv,
                spin_unlock_irqrestore(&card->buffer_lock, flags);
                break;
        default:
+               kfree(packet);
                netdev_err(priv->dev, "can't transfer buffer of type %d\n",
                           type);
                err = -EINVAL;
index dae8dbb..8d3ab37 100644 (file)
@@ -819,8 +819,10 @@ mwifiex_scan_setup_scan_config(struct mwifiex_private *priv,
                        wildcard_ssid_tlv->header.len = cpu_to_le16(
                                (u16) (ssid_len + sizeof(wildcard_ssid_tlv->
                                                         max_ssid_length)));
-                       wildcard_ssid_tlv->max_ssid_length =
-                               user_scan_in->ssid_list[ssid_idx].max_len;
+
+                       /* max_ssid_length = 0 tells firmware to perform
+                          specific scan for the SSID filled */
+                       wildcard_ssid_tlv->max_ssid_length = 0;
 
                        memcpy(wildcard_ssid_tlv->ssid,
                               user_scan_in->ssid_list[ssid_idx].ssid,
@@ -1469,7 +1471,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
                               s32 rssi, const u8 *ie_buf, size_t ie_len,
                               u16 beacon_period, u16 cap_info_bitmap, u8 band)
 {
-       struct mwifiex_bssdescriptor *bss_desc = NULL;
+       struct mwifiex_bssdescriptor *bss_desc;
        int ret;
        unsigned long flags;
        u8 *beacon_ie;
@@ -1484,6 +1486,7 @@ mwifiex_update_curr_bss_params(struct mwifiex_private *priv, u8 *bssid,
 
        beacon_ie = kmemdup(ie_buf, ie_len, GFP_KERNEL);
        if (!beacon_ie) {
+               kfree(bss_desc);
                dev_err(priv->adapter->dev, " failed to alloc beacon_ie\n");
                return -ENOMEM;
        }
index f18df82..78d0d69 100644 (file)
@@ -588,8 +588,6 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
 
        WARN_ON(priv->fw_state != FW_STATE_READY);
 
-       cancel_work_sync(&priv->work);
-
        p54spi_power_off(priv);
        spin_lock_irqsave(&priv->tx_lock, flags);
        INIT_LIST_HEAD(&priv->tx_pending);
@@ -597,6 +595,8 @@ static void p54spi_op_stop(struct ieee80211_hw *dev)
 
        priv->fw_state = FW_STATE_OFF;
        mutex_unlock(&priv->mutex);
+
+       cancel_work_sync(&priv->work);
 }
 
 static int __devinit p54spi_probe(struct spi_device *spi)
@@ -656,6 +656,7 @@ static int __devinit p54spi_probe(struct spi_device *spi)
        init_completion(&priv->fw_comp);
        INIT_LIST_HEAD(&priv->tx_pending);
        mutex_init(&priv->mutex);
+       spin_lock_init(&priv->tx_lock);
        SET_IEEE80211_DEV(hw, &spi->dev);
        priv->common.open = p54spi_op_start;
        priv->common.stop = p54spi_op_stop;
index d97a2ca..bc2ba80 100644 (file)
@@ -778,7 +778,7 @@ prism54_get_essid(struct net_device *ndev, struct iw_request_info *info,
                dwrq->flags = 0;
                dwrq->length = 0;
        }
-       essid->octets[essid->length] = '\0';
+       essid->octets[dwrq->length] = '\0';
        memcpy(extra, essid->octets, dwrq->length);
        kfree(essid);
 
index 3f183a1..1ba079d 100644 (file)
@@ -3771,7 +3771,7 @@ static void rt2800_efuse_read(struct rt2x00_dev *rt2x00dev, unsigned int i)
        /* Apparently the data is read from end to start */
        rt2800_register_read_lock(rt2x00dev, EFUSE_DATA3, &reg);
        /* The returned value is in CPU order, but eeprom is le */
-       rt2x00dev->eeprom[i] = cpu_to_le32(reg);
+       *(u32 *)&rt2x00dev->eeprom[i] = cpu_to_le32(reg);
        rt2800_register_read_lock(rt2x00dev, EFUSE_DATA2, &reg);
        *(u32 *)&rt2x00dev->eeprom[i + 2] = cpu_to_le32(reg);
        rt2800_register_read_lock(rt2x00dev, EFUSE_DATA1, &reg);
index f156579..3778763 100644 (file)
@@ -919,6 +919,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x050d, 0x935b) },
        /* Buffalo */
        { USB_DEVICE(0x0411, 0x00e8) },
+       { USB_DEVICE(0x0411, 0x0158) },
        { USB_DEVICE(0x0411, 0x016f) },
        { USB_DEVICE(0x0411, 0x01a2) },
        /* Corega */
index 2ec5c00..99ff12d 100644 (file)
@@ -943,6 +943,7 @@ struct rt2x00_dev {
         * Powersaving work
         */
        struct delayed_work autowakeup_work;
+       struct work_struct sleep_work;
 
        /*
         * Data queue arrays for RX, TX, Beacon and ATIM.
index e1fb2a8..edd317f 100644 (file)
@@ -465,6 +465,23 @@ static u8 *rt2x00lib_find_ie(u8 *data, unsigned int len, u8 ie)
        return NULL;
 }
 
+static void rt2x00lib_sleep(struct work_struct *work)
+{
+       struct rt2x00_dev *rt2x00dev =
+           container_of(work, struct rt2x00_dev, sleep_work);
+
+       if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+               return;
+
+       /*
+        * Check again is powersaving is enabled, to prevent races from delayed
+        * work execution.
+        */
+       if (!test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
+               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
+                                IEEE80211_CONF_CHANGE_PS);
+}
+
 static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
                                      struct sk_buff *skb,
                                      struct rxdone_entry_desc *rxdesc)
@@ -512,8 +529,7 @@ static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
        cam |= (tim_ie->bitmap_ctrl & 0x01);
 
        if (!cam && !test_bit(CONFIG_POWERSAVING, &rt2x00dev->flags))
-               rt2x00lib_config(rt2x00dev, &rt2x00dev->hw->conf,
-                                IEEE80211_CONF_CHANGE_PS);
+               queue_work(rt2x00dev->workqueue, &rt2x00dev->sleep_work);
 }
 
 static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev,
@@ -1141,6 +1157,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
 
        INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
        INIT_DELAYED_WORK(&rt2x00dev->autowakeup_work, rt2x00lib_autowakeup);
+       INIT_WORK(&rt2x00dev->sleep_work, rt2x00lib_sleep);
 
        /*
         * Let the driver probe the device to detect the capabilities.
@@ -1197,6 +1214,7 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
         */
        cancel_work_sync(&rt2x00dev->intf_work);
        cancel_delayed_work_sync(&rt2x00dev->autowakeup_work);
+       cancel_work_sync(&rt2x00dev->sleep_work);
        if (rt2x00_is_usb(rt2x00dev)) {
                del_timer_sync(&rt2x00dev->txstatus_timer);
                cancel_work_sync(&rt2x00dev->rxdone_work);
index db52628..55c8e50 100644 (file)
@@ -395,7 +395,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
        if (mac->link_state != MAC80211_LINKED)
                return;
 
-       spin_lock(&rtlpriv->locks.lps_lock);
+       spin_lock_irq(&rtlpriv->locks.lps_lock);
 
        /* Idle for a while if we connect to AP a while ago. */
        if (mac->cnt_after_linked >= 2) {
@@ -407,7 +407,7 @@ void rtl_lps_enter(struct ieee80211_hw *hw)
                }
        }
 
-       spin_unlock(&rtlpriv->locks.lps_lock);
+       spin_unlock_irq(&rtlpriv->locks.lps_lock);
 }
 
 /*Leave the leisure power save mode.*/
@@ -416,8 +416,9 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
        struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+       unsigned long flags;
 
-       spin_lock(&rtlpriv->locks.lps_lock);
+       spin_lock_irqsave(&rtlpriv->locks.lps_lock, flags);
 
        if (ppsc->fwctrl_lps) {
                if (ppsc->dot11_psmode != EACTIVE) {
@@ -438,7 +439,7 @@ void rtl_lps_leave(struct ieee80211_hw *hw)
                        rtl_lps_set_psmode(hw, EACTIVE);
                }
        }
-       spin_unlock(&rtlpriv->locks.lps_lock);
+       spin_unlock_irqrestore(&rtlpriv->locks.lps_lock, flags);
 }
 
 /* For sw LPS*/
@@ -539,9 +540,9 @@ void rtl_swlps_rf_awake(struct ieee80211_hw *hw)
                RT_CLEAR_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM);
        }
 
-       spin_lock(&rtlpriv->locks.lps_lock);
+       spin_lock_irq(&rtlpriv->locks.lps_lock);
        rtl_ps_set_rf_state(hw, ERFON, RF_CHANGE_BY_PS);
-       spin_unlock(&rtlpriv->locks.lps_lock);
+       spin_unlock_irq(&rtlpriv->locks.lps_lock);
 }
 
 void rtl_swlps_rfon_wq_callback(void *data)
@@ -574,9 +575,9 @@ void rtl_swlps_rf_sleep(struct ieee80211_hw *hw)
        if (rtlpriv->link_info.busytraffic)
                return;
 
-       spin_lock(&rtlpriv->locks.lps_lock);
+       spin_lock_irq(&rtlpriv->locks.lps_lock);
        rtl_ps_set_rf_state(hw, ERFSLEEP, RF_CHANGE_BY_PS);
-       spin_unlock(&rtlpriv->locks.lps_lock);
+       spin_unlock_irq(&rtlpriv->locks.lps_lock);
 
        if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM &&
                !RT_IN_PS_LEVEL(ppsc, RT_PS_LEVEL_ASPM)) {
index 128ccb7..fc29c67 100644 (file)
@@ -559,7 +559,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
                                                break;
                                        }
                                /* Fail if SSID isn't present in the filters */
-                               if (j == req->n_ssids) {
+                               if (j == cmd->n_ssids) {
                                        ret = -EINVAL;
                                        goto out_free;
                                }
index 0cb594c..1ae270e 100644 (file)
@@ -1021,7 +1021,7 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
                pending_idx = *((u16 *)skb->data);
                xen_netbk_idx_release(netbk, pending_idx);
                for (j = start; j < i; j++) {
-                       pending_idx = frag_get_pending_idx(&shinfo->frags[i]);
+                       pending_idx = frag_get_pending_idx(&shinfo->frags[j]);
                        xen_netbk_idx_release(netbk, pending_idx);
                }
 
index 6d3dd39..19c0115 100644 (file)
@@ -60,27 +60,27 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map);
  */
 struct device_node *of_irq_find_parent(struct device_node *child)
 {
-       struct device_node *p, *c = child;
+       struct device_node *p;
        const __be32 *parp;
 
-       if (!of_node_get(c))
+       if (!of_node_get(child))
                return NULL;
 
        do {
-               parp = of_get_property(c, "interrupt-parent", NULL);
+               parp = of_get_property(child, "interrupt-parent", NULL);
                if (parp == NULL)
-                       p = of_get_parent(c);
+                       p = of_get_parent(child);
                else {
                        if (of_irq_workarounds & OF_IMAP_NO_PHANDLE)
                                p = of_node_get(of_irq_dflt_pic);
                        else
                                p = of_find_node_by_phandle(be32_to_cpup(parp));
                }
-               of_node_put(c);
-               c = p;
+               of_node_put(child);
+               child = p;
        } while (p && of_get_property(p, "#interrupt-cells", NULL) == NULL);
 
-       return (p == child) ? NULL : p;
+       return p;
 }
 
 /**
@@ -424,6 +424,8 @@ void __init of_irq_init(const struct of_device_id *matches)
 
                desc->dev = np;
                desc->interrupt_parent = of_irq_find_parent(np);
+               if (desc->interrupt_parent == np)
+                       desc->interrupt_parent = NULL;
                list_add_tail(&desc->list, &intc_desc_list);
        }
 
index b6f9749..f02b523 100644 (file)
@@ -76,6 +76,7 @@ config PCI_IOV
 
 config PCI_PRI
        bool "PCI PRI support"
+       depends on PCI
        select PCI_ATS
        help
          PRI is the PCI Page Request Interface. It allows PCI devices that are
index 596172b..fce1c54 100644 (file)
@@ -459,8 +459,17 @@ static int add_bridge(acpi_handle handle)
 {
        acpi_status status;
        unsigned long long tmp;
+       struct acpi_pci_root *root;
        acpi_handle dummy_handle;
 
+       /*
+        * We shouldn't use this bridge if PCIe native hotplug control has been
+        * granted by the BIOS for it.
+        */
+       root = acpi_pci_find_root(handle);
+       if (root && (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL))
+               return -ENODEV;
+
        /* if the bridge doesn't have _STA, we assume it is always there */
        status = acpi_get_handle(handle, "_STA", &dummy_handle);
        if (ACPI_SUCCESS(status)) {
@@ -1376,13 +1385,23 @@ static void handle_hotplug_event_func(acpi_handle handle, u32 type,
 static acpi_status
 find_root_bridges(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
+       struct acpi_pci_root *root;
        int *count = (int *)context;
 
-       if (acpi_is_root_bridge(handle)) {
-               acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-                               handle_hotplug_event_bridge, NULL);
-                       (*count)++;
-       }
+       if (!acpi_is_root_bridge(handle))
+               return AE_OK;
+
+       root = acpi_pci_find_root(handle);
+       if (!root)
+               return AE_OK;
+
+       if (root->osc_control_set & OSC_PCI_EXPRESS_NATIVE_HP_CONTROL)
+               return AE_OK;
+
+       (*count)++;
+       acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+                                   handle_hotplug_event_bridge, NULL);
+
        return AE_OK ;
 }
 
index 1e9c9aa..085dbb5 100644 (file)
@@ -213,9 +213,6 @@ static int board_added(struct slot *p_slot)
                goto err_exit;
        }
 
-       /* Wait for 1 second after checking link training status */
-       msleep(1000);
-
        /* Check for a power fault */
        if (ctrl->power_fault_detected || pciehp_query_power_fault(p_slot)) {
                ctrl_err(ctrl, "Power fault on slot %s\n", slot_name(p_slot));
index 96dc473..7b14148 100644 (file)
@@ -280,6 +280,14 @@ int pciehp_check_link_status(struct controller *ctrl)
         else
                 msleep(1000);
 
+       /*
+        * Need to wait for 1000 ms after Data Link Layer Link Active
+        * (DLLLA) bit reads 1b before sending configuration request.
+        * We need it before checking Link Training (LT) bit becuase
+        * LT is still set even after DLLLA bit is set on some platform.
+        */
+       msleep(1000);
+
        retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
        if (retval) {
                ctrl_err(ctrl, "Cannot read LNKSTATUS register\n");
@@ -294,6 +302,16 @@ int pciehp_check_link_status(struct controller *ctrl)
                return retval;
        }
 
+       /*
+        * If the port supports Link speeds greater than 5.0 GT/s, we
+        * must wait for 100 ms after Link training completes before
+        * sending configuration request.
+        */
+       if (ctrl->pcie->port->subordinate->max_bus_speed > PCIE_SPEED_5_0GT)
+               msleep(100);
+
+       pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
+
        return retval;
 }
 
@@ -484,7 +502,6 @@ int pciehp_power_on_slot(struct slot * slot)
        u16 slot_cmd;
        u16 cmd_mask;
        u16 slot_status;
-       u16 lnk_status;
        int retval = 0;
 
        /* Clear sticky power-fault bit from previous power failures */
@@ -516,14 +533,6 @@ int pciehp_power_on_slot(struct slot * slot)
        ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
                 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
 
-       retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
-       if (retval) {
-               ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n",
-                               __func__);
-               return retval;
-       }
-       pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
-
        return retval;
 }
 
index aca972b..dd7e0c5 100644 (file)
@@ -278,8 +278,8 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
 
 static int is_shpc_capable(struct pci_dev *dev)
 {
-       if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
-                                               PCI_DEVICE_ID_AMD_GOLAM_7450))
+       if (dev->vendor == PCI_VENDOR_ID_AMD &&
+           dev->device == PCI_DEVICE_ID_AMD_GOLAM_7450)
                return 1;
        if (!pci_find_capability(dev, PCI_CAP_ID_SHPC))
                return 0;
index 36547f0..75ba231 100644 (file)
@@ -944,8 +944,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
        ctrl->pci_dev = pdev;  /* pci_dev of the P2P bridge */
        ctrl_dbg(ctrl, "Hotplug Controller:\n");
 
-       if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
-                               PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+       if (pdev->vendor == PCI_VENDOR_ID_AMD &&
+           pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450) {
                /* amd shpc driver doesn't use Base Offset; assume 0 */
                ctrl->mmio_base = pci_resource_start(pdev, 0);
                ctrl->mmio_size = pci_resource_len(pdev, 0);
index ef56644..e17e2f8 100644 (file)
@@ -2,23 +2,17 @@
 # PINCTRL infrastructure and drivers
 #
 
-menuconfig PINCTRL
-       bool "PINCTRL Support"
+config PINCTRL
+       bool
        depends on EXPERIMENTAL
-       help
-         This enables the PINCTRL subsystem for controlling pins
-         on chip packages, for example multiplexing pins on primarily
-         PGA and BGA packages for systems on chip.
-
-         If unsure, say N.
 
 if PINCTRL
 
+menu "Pin controllers"
+       depends on PINCTRL
+
 config PINMUX
        bool "Support pinmux controllers"
-       help
-         Say Y here if you want the pincontrol subsystem to handle pin
-         multiplexing drivers.
 
 config DEBUG_PINCTRL
        bool "Debug PINCTRL calls"
@@ -30,14 +24,12 @@ config PINMUX_SIRF
        bool "CSR SiRFprimaII pinmux driver"
        depends on ARCH_PRIMA2
        select PINMUX
-       help
-         Say Y here to enable the SiRFprimaII pinmux driver
 
 config PINMUX_U300
        bool "U300 pinmux driver"
        depends on ARCH_U300
        select PINMUX
-       help
-         Say Y here to enable the U300 pinmux driver
+
+endmenu
 
 endif
index f4e3d82..7f43cf8 100644 (file)
@@ -83,8 +83,10 @@ config DELL_LAPTOP
        depends on EXPERIMENTAL
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL || RFKILL = n
-       depends on POWER_SUPPLY
        depends on SERIO_I8042
+       select POWER_SUPPLY
+       select LEDS_CLASS
+       select NEW_LEDS
        default n
        ---help---
        This driver adds support for rfkill and backlight control to Dell
index a43cfd9..d93e962 100644 (file)
@@ -589,14 +589,14 @@ static const struct backlight_ops dell_ops = {
        .update_status  = dell_send_intensity,
 };
 
-static void touchpad_led_on()
+static void touchpad_led_on(void)
 {
        int command = 0x97;
        char data = 1;
        i8042_command(&data, command | 1 << 12);
 }
 
-static void touchpad_led_off()
+static void touchpad_led_off(void)
 {
        int command = 0x97;
        char data = 2;
index d9fb729..fb73008 100644 (file)
@@ -952,7 +952,7 @@ static int ps3_vuart_bus_interrupt_get(void)
        }
 
        result = request_irq(vuart_bus_priv.virq, ps3_vuart_irq_handler,
-               IRQF_DISABLED, "vuart", &vuart_bus_priv);
+               0, "vuart", &vuart_bus_priv);
 
        if (result) {
                pr_debug("%s:%d: request_irq failed (%d)\n",
index cc328de..8c3f5ad 100644 (file)
@@ -167,7 +167,7 @@ int ps3stor_setup(struct ps3_storage_device *dev, irq_handler_t handler)
                goto fail_close_device;
        }
 
-       error = request_irq(dev->irq, handler, IRQF_DISABLED,
+       error = request_irq(dev->irq, handler, 0,
                            dev->sbd.core.driver->name, dev);
        if (error) {
                dev_err(&dev->sbd.core, "%s:%u: request_irq failed %d\n",
index 5abeb3a..298c6c6 100644 (file)
@@ -160,7 +160,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id)
                        break;
        }
 
-       if (!ri)
+       if (i == ARRAY_SIZE(aat2870_regulators))
                return NULL;
 
        ri->enable_addr = AAT2870_LDO_EN;
index 669d021..938398f 100644 (file)
@@ -2799,8 +2799,8 @@ void regulator_unregister(struct regulator_dev *rdev)
        list_del(&rdev->list);
        if (rdev->supply)
                regulator_put(rdev->supply);
-       device_unregister(&rdev->dev);
        kfree(rdev->constraints);
+       device_unregister(&rdev->dev);
        mutex_unlock(&regulator_list_mutex);
 }
 EXPORT_SYMBOL_GPL(regulator_unregister);
index 66d2d60..b552aae 100644 (file)
@@ -664,10 +664,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
 
        switch (id) {
        case TPS65910_REG_VDD1:
-               dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                if (dcdc_mult == 1)
                        dcdc_mult--;
-               vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
+               vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
                tps65910_modify_bits(pmic, TPS65910_VDD1,
                                (dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
@@ -675,10 +675,10 @@ static int tps65910_set_voltage_dcdc(struct regulator_dev *dev,
                tps65910_reg_write(pmic, TPS65910_VDD1_OP, vsel);
                break;
        case TPS65910_REG_VDD2:
-               dcdc_mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                if (dcdc_mult == 1)
                        dcdc_mult--;
-               vsel = (selector % VDD1_2_NUM_VOLTS) + 3;
+               vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
                tps65910_modify_bits(pmic, TPS65910_VDD2,
                                (dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
@@ -756,9 +756,9 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
        switch (id) {
        case TPS65910_REG_VDD1:
        case TPS65910_REG_VDD2:
-               mult = (selector / VDD1_2_NUM_VOLTS) + 1;
+               mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                volt = VDD1_2_MIN_VOLT +
-                               (selector % VDD1_2_NUM_VOLTS) * VDD1_2_OFFSET;
+                               (selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET;
                break;
        case TPS65911_REG_VDDCTRL:
                volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET);
@@ -947,6 +947,8 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
 
                if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) {
                        pmic->desc[i].ops = &tps65910_ops_dcdc;
+                       pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE *
+                                                       VDD1_2_NUM_VOLT_COARSE;
                } else if (i == TPS65910_REG_VDD3) {
                        if (tps65910_chip_id(tps65910) == TPS65910)
                                pmic->desc[i].ops = &tps65910_ops_vdd3;
index ee8747f..11cc308 100644 (file)
@@ -71,6 +71,7 @@ struct twlreg_info {
 #define VREG_TYPE              1
 #define VREG_REMAP             2
 #define VREG_DEDICATED         3       /* LDO control */
+#define VREG_VOLTAGE_SMPS_4030 9
 /* TWL6030 register offsets */
 #define VREG_TRANS             1
 #define VREG_STATE             2
@@ -514,6 +515,32 @@ static struct regulator_ops twl4030ldo_ops = {
        .get_status     = twl4030reg_get_status,
 };
 
+static int
+twl4030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
+                       unsigned *selector)
+{
+       struct twlreg_info *info = rdev_get_drvdata(rdev);
+       int vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
+
+       twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE_SMPS_4030,
+               vsel);
+       return 0;
+}
+
+static int twl4030smps_get_voltage(struct regulator_dev *rdev)
+{
+       struct twlreg_info *info = rdev_get_drvdata(rdev);
+       int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
+               VREG_VOLTAGE_SMPS_4030);
+
+       return vsel * 12500 + 600000;
+}
+
+static struct regulator_ops twl4030smps_ops = {
+       .set_voltage    = twl4030smps_set_voltage,
+       .get_voltage    = twl4030smps_get_voltage,
+};
+
 static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
@@ -856,6 +883,21 @@ static struct regulator_ops twlsmps_ops = {
                }, \
        }
 
+#define TWL4030_ADJUSTABLE_SMPS(label, offset, num, turnon_delay, remap_conf) \
+       { \
+       .base = offset, \
+       .id = num, \
+       .delay = turnon_delay, \
+       .remap = remap_conf, \
+       .desc = { \
+               .name = #label, \
+               .id = TWL4030_REG_##label, \
+               .ops = &twl4030smps_ops, \
+               .type = REGULATOR_VOLTAGE, \
+               .owner = THIS_MODULE, \
+               }, \
+       }
+
 #define TWL6030_ADJUSTABLE_LDO(label, offset, min_mVolts, max_mVolts) { \
        .base = offset, \
        .min_mV = min_mVolts, \
@@ -947,8 +989,8 @@ static struct twlreg_info twl_regs[] = {
        TWL4030_ADJUSTABLE_LDO(VINTANA2, 0x43, 12, 100, 0x08),
        TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08),
        TWL4030_ADJUSTABLE_LDO(VIO, 0x4b, 14, 1000, 0x08),
-       TWL4030_ADJUSTABLE_LDO(VDD1, 0x55, 15, 1000, 0x08),
-       TWL4030_ADJUSTABLE_LDO(VDD2, 0x63, 16, 1000, 0x08),
+       TWL4030_ADJUSTABLE_SMPS(VDD1, 0x55, 15, 1000, 0x08),
+       TWL4030_ADJUSTABLE_SMPS(VDD2, 0x63, 16, 1000, 0x08),
        TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08),
        TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08),
        TWL4030_FIXED_LDO(VUSB3V1, 0x77, 3100, 19, 150, 0x08),
index d335448..bb21f44 100644 (file)
@@ -76,12 +76,15 @@ static inline unsigned char vrtc_is_updating(void)
 /*
  * rtc_time's year contains the increment over 1900, but vRTC's YEAR
  * register can't be programmed to value larger than 0x64, so vRTC
- * driver chose to use 1960 (1970 is UNIX time start point) as the base,
+ * driver chose to use 1972 (1970 is UNIX time start point) as the base,
  * and does the translation at read/write time.
  *
- * Why not just use 1970 as the offset? it's because using 1960 will
+ * Why not just use 1970 as the offset? it's because using 1972 will
  * make it consistent in leap year setting for both vrtc and low-level
- * physical rtc devices.
+ * physical rtc devices. Then why not use 1960 as the offset? If we use
+ * 1960, for a device's first use, its YEAR register is 0 and the system
+ * year will be parsed as 1960 which is not a valid UNIX time and will
+ * cause many applications to fail mysteriously.
  */
 static int mrst_read_time(struct device *dev, struct rtc_time *time)
 {
@@ -99,10 +102,10 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time)
        time->tm_year = vrtc_cmos_read(RTC_YEAR);
        spin_unlock_irqrestore(&rtc_lock, flags);
 
-       /* Adjust for the 1960/1900 */
-       time->tm_year += 60;
+       /* Adjust for the 1972/1900 */
+       time->tm_year += 72;
        time->tm_mon--;
-       return RTC_24H;
+       return rtc_valid_tm(time);
 }
 
 static int mrst_set_time(struct device *dev, struct rtc_time *time)
@@ -119,9 +122,9 @@ static int mrst_set_time(struct device *dev, struct rtc_time *time)
        min = time->tm_min;
        sec = time->tm_sec;
 
-       if (yrs < 70 || yrs > 138)
+       if (yrs < 72 || yrs > 138)
                return -EINVAL;
-       yrs -= 60;
+       yrs -= 72;
 
        spin_lock_irqsave(&rtc_lock, flags);
 
index b3eba3c..e4b6880 100644 (file)
@@ -220,7 +220,7 @@ static void puv3_rtc_enable(struct platform_device *pdev, int en)
        }
 }
 
-static int puv3_rtc_remove(struct platform_device *dev)
+static int __devexit puv3_rtc_remove(struct platform_device *dev)
 {
        struct rtc_device *rtc = platform_get_drvdata(dev);
 
@@ -236,7 +236,7 @@ static int puv3_rtc_remove(struct platform_device *dev)
        return 0;
 }
 
-static int puv3_rtc_probe(struct platform_device *pdev)
+static int __devinit puv3_rtc_probe(struct platform_device *pdev)
 {
        struct rtc_device *rtc;
        struct resource *res;
index 43068fb..1b6d924 100644 (file)
@@ -641,6 +641,8 @@ static int __init zcore_init(void)
 
        if (ipl_info.type != IPL_TYPE_FCP_DUMP)
                return -ENODATA;
+       if (OLDMEM_BASE)
+               return -ENODATA;
 
        zcore_dbf = debug_register("zcore", 4, 1, 4 * sizeof(long));
        debug_register_view(zcore_dbf, &debug_sprintf_view);
index b77ae51..ec94f04 100644 (file)
@@ -1271,18 +1271,16 @@ ap_config_timeout(unsigned long ptr)
 }
 
 /**
- * ap_schedule_poll_timer(): Schedule poll timer.
+ * __ap_schedule_poll_timer(): Schedule poll timer.
  *
  * Set up the timer to run the poll tasklet
  */
-static inline void ap_schedule_poll_timer(void)
+static inline void __ap_schedule_poll_timer(void)
 {
        ktime_t hr_time;
 
        spin_lock_bh(&ap_poll_timer_lock);
-       if (ap_using_interrupts() || ap_suspend_flag)
-               goto out;
-       if (hrtimer_is_queued(&ap_poll_timer))
+       if (hrtimer_is_queued(&ap_poll_timer) || ap_suspend_flag)
                goto out;
        if (ktime_to_ns(hrtimer_expires_remaining(&ap_poll_timer)) <= 0) {
                hr_time = ktime_set(0, poll_timeout);
@@ -1293,6 +1291,18 @@ out:
        spin_unlock_bh(&ap_poll_timer_lock);
 }
 
+/**
+ * ap_schedule_poll_timer(): Schedule poll timer.
+ *
+ * Set up the timer to run the poll tasklet
+ */
+static inline void ap_schedule_poll_timer(void)
+{
+       if (ap_using_interrupts())
+               return;
+       __ap_schedule_poll_timer();
+}
+
 /**
  * ap_poll_read(): Receive pending reply messages from an AP device.
  * @ap_dev: pointer to the AP device
@@ -1374,8 +1384,9 @@ static int ap_poll_write(struct ap_device *ap_dev, unsigned long *flags)
                        *flags |= 1;
                *flags |= 2;
                break;
-       case AP_RESPONSE_Q_FULL:
        case AP_RESPONSE_RESET_IN_PROGRESS:
+               __ap_schedule_poll_timer();
+       case AP_RESPONSE_Q_FULL:
                *flags |= 2;
                break;
        case AP_RESPONSE_MESSAGE_TOO_BIG:
index fa80ba1..9b66d2d 100644 (file)
@@ -4,7 +4,7 @@ menu "S/390 network device drivers"
 config LCS
        def_tristate m
        prompt "Lan Channel Station Interface"
-       depends on CCW && NETDEVICES && (NET_ETHERNET || TR || FDDI)
+       depends on CCW && NETDEVICES && (ETHERNET || TR || FDDI)
        help
           Select this option if you want to use LCS networking on IBM System z.
           This device driver supports Token Ring (IEEE 802.5),
index c28713d..863fc21 100644 (file)
@@ -50,7 +50,7 @@
 #include "lcs.h"
 
 
-#if !defined(CONFIG_NET_ETHERNET) && \
+#if !defined(CONFIG_ETHERNET) && \
     !defined(CONFIG_TR) && !defined(CONFIG_FDDI)
 #error Cannot compile lcs.c without some net devices switched on.
 #endif
@@ -1634,7 +1634,7 @@ lcs_startlan_auto(struct lcs_card *card)
        int rc;
 
        LCS_DBF_TEXT(2, trace, "strtauto");
-#ifdef CONFIG_NET_ETHERNET
+#ifdef CONFIG_ETHERNET
        card->lan_type = LCS_FRAME_TYPE_ENET;
        rc = lcs_send_startlan(card, LCS_INITIATOR_TCPIP);
        if (rc == 0)
@@ -2166,7 +2166,7 @@ lcs_new_device(struct ccwgroup_device *ccwgdev)
                goto netdev_out;
        }
        switch (card->lan_type) {
-#ifdef CONFIG_NET_ETHERNET
+#ifdef CONFIG_ETHERNET
        case LCS_FRAME_TYPE_ENET:
                card->lan_type_trans = eth_type_trans;
                dev = alloc_etherdev(0);
index 3251333..b6a6356 100644 (file)
@@ -1994,6 +1994,8 @@ static struct net_device *netiucv_init_netdevice(char *username)
                           netiucv_setup_netdevice);
        if (!dev)
                return NULL;
+       if (dev_alloc_name(dev, dev->name) < 0)
+               goto out_netdev;
 
        privptr = netdev_priv(dev);
        privptr->fsm = init_fsm("netiucvdev", dev_state_names,
index b77c65e..4abc79d 100644 (file)
@@ -236,8 +236,7 @@ static inline int qeth_is_ipa_enabled(struct qeth_ipa_info *ipa,
 #define QETH_IN_BUF_COUNT_MAX 128
 #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
 #define QETH_IN_BUF_REQUEUE_THRESHOLD(card) \
-               ((card)->ssqd.qdioac1 & AC1_SIGA_INPUT_NEEDED ? 1 : \
-                ((card)->qdio.in_buf_pool.buf_count / 2))
+                ((card)->qdio.in_buf_pool.buf_count / 2)
 
 /* buffers we have to be behind before we get a PCI */
 #define QETH_PCI_THRESHOLD_A(card) ((card)->qdio.in_buf_pool.buf_count+1)
index 8153443..fff57de 100644 (file)
@@ -881,7 +881,6 @@ EXPORT_SYMBOL_GPL(qeth_do_run_thread);
 void qeth_schedule_recovery(struct qeth_card *card)
 {
        QETH_CARD_TEXT(card, 2, "startrec");
-       WARN_ON(1);
        if (qeth_set_thread_start_bit(card, QETH_RECOVER_THREAD) == 0)
                schedule_work(&card->kernel_thread_starter);
 }
index e4c1176..4d5307d 100644 (file)
@@ -2756,11 +2756,13 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
        struct neighbour *n = NULL;
        struct dst_entry *dst;
 
+       rcu_read_lock();
        dst = skb_dst(skb);
        if (dst)
                n = dst_get_neighbour(dst);
        if (n) {
                cast_type = n->type;
+               rcu_read_unlock();
                if ((cast_type == RTN_BROADCAST) ||
                    (cast_type == RTN_MULTICAST) ||
                    (cast_type == RTN_ANYCAST))
@@ -2768,6 +2770,8 @@ int inline qeth_l3_get_cast_type(struct qeth_card *card, struct sk_buff *skb)
                else
                        return RTN_UNSPEC;
        }
+       rcu_read_unlock();
+
        /* try something else */
        if (skb->protocol == ETH_P_IPV6)
                return (skb_network_header(skb)[24] == 0xff) ?
@@ -2847,6 +2851,8 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
        }
 
        hdr->hdr.l3.length = skb->len - sizeof(struct qeth_hdr);
+
+       rcu_read_lock();
        dst = skb_dst(skb);
        if (dst)
                n = dst_get_neighbour(dst);
@@ -2893,6 +2899,7 @@ static void qeth_l3_fill_header(struct qeth_card *card, struct qeth_hdr *hdr,
                                QETH_CAST_UNICAST | QETH_HDR_PASSTHRU;
                }
        }
+       rcu_read_unlock();
 }
 
 static inline void qeth_l3_hdr_csum(struct qeth_card *card,
index 0ea2fbf..d979bb2 100644 (file)
@@ -335,10 +335,10 @@ static ssize_t qeth_l3_dev_sniffer_store(struct device *dev,
                                        QETH_IN_BUF_COUNT_MAX)
                                qeth_realloc_buffer_pool(card,
                                        QETH_IN_BUF_COUNT_MAX);
-                       break;
                } else
                        rc = -EPERM;
-       default:   /* fall through */
+               break;
+       default:
                rc = -EINVAL;
        }
 out:
index 4aa76d6..705e13e 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
@@ -1109,6 +1110,9 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
                unique_id++;
        }
 
+       pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+                              PCIE_LINK_STATE_CLKPM);
+
        error = pci_enable_device(pdev);
        if (error)
                goto out;
index e76107b..865d452 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/types.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
@@ -3922,6 +3923,10 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h)
                dev_warn(&h->pdev->dev, "controller appears to be disabled\n");
                return -ENODEV;
        }
+
+       pci_disable_link_state(h->pdev, PCIE_LINK_STATE_L0S |
+                              PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM);
+
        err = pci_enable_device(h->pdev);
        if (err) {
                dev_warn(&h->pdev->dev, "unable to enable PCI device\n");
index 8889b1b..4e041f6 100644 (file)
@@ -2802,6 +2802,11 @@ _scsih_error_recovery_delete_devices(struct MPT2SAS_ADAPTER *ioc)
 
        if (ioc->is_driver_loading)
                return;
+
+       fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+       if (!fw_event)
+               return;
+
        fw_event->event = MPT2SAS_REMOVE_UNRESPONDING_DEVICES;
        fw_event->ioc = ioc;
        _scsih_fw_event_add(ioc, fw_event);
index 06bc265..f85cfa6 100644 (file)
@@ -1409,6 +1409,8 @@ static void scsi_kill_request(struct request *req, struct request_queue *q)
 
        blk_start_request(req);
 
+       scmd_printk(KERN_INFO, cmd, "killing request\n");
+
        sdev = cmd->device;
        starget = scsi_target(sdev);
        shost = sdev->host;
@@ -1490,7 +1492,6 @@ static void scsi_request_fn(struct request_queue *q)
        struct request *req;
 
        if (!sdev) {
-               printk("scsi: killing requests for dead queue\n");
                while ((req = blk_peek_request(q)) != NULL)
                        scsi_kill_request(req, q);
                return;
index 72273a0..b3c6d95 100644 (file)
@@ -319,11 +319,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
        return sdev;
 
 out_device_destroy:
-       scsi_device_set_state(sdev, SDEV_DEL);
-       transport_destroy_device(&sdev->sdev_gendev);
-       put_device(&sdev->sdev_dev);
-       scsi_free_queue(sdev->request_queue);
-       put_device(&sdev->sdev_gendev);
+       __scsi_remove_device(sdev);
 out:
        if (display_failure_msg)
                printk(ALLOC_FAILURE_MSG, __func__);
index 24e6cec..67e272a 100644 (file)
@@ -7,3 +7,11 @@ obj-$(CONFIG_HAVE_CLK)         += clk/
 obj-$(CONFIG_MAPLE)            += maple/
 obj-$(CONFIG_SUPERHYWAY)       += superhyway/
 obj-$(CONFIG_GENERIC_GPIO)     += pfc.o
+
+#
+# For the moment we only use this framework for ARM-based SH/R-Mobile
+# platforms and generic SH. SH-based SH-Mobile platforms are still using
+# an older framework that is pending up-porting, at which point this
+# special casing can go away.
+#
+obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE)    += pm_runtime.o
index dc8d022..db257a3 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/seq_file.h>
 #include <linux/err.h>
 #include <linux/io.h>
-#include <linux/debugfs.h>
 #include <linux/cpufreq.h>
 #include <linux/clk.h>
 #include <linux/sh_clk.h>
@@ -173,6 +172,26 @@ long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
        return clk_rate_round_helper(&div_range_round);
 }
 
+static long clk_rate_mult_range_iter(unsigned int pos,
+                                     struct clk_rate_round_data *rounder)
+{
+       return clk_get_rate(rounder->arg) * pos;
+}
+
+long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min,
+                              unsigned int mult_max, unsigned long rate)
+{
+       struct clk_rate_round_data mult_range_round = {
+               .min    = mult_min,
+               .max    = mult_max,
+               .func   = clk_rate_mult_range_iter,
+               .arg    = clk_get_parent(clk),
+               .rate   = rate,
+       };
+
+       return clk_rate_round_helper(&mult_range_round);
+}
+
 int clk_rate_table_find(struct clk *clk,
                        struct cpufreq_frequency_table *freq_table,
                        unsigned long rate)
@@ -205,9 +224,6 @@ int clk_reparent(struct clk *child, struct clk *parent)
                list_add(&child->sibling, &parent->children);
        child->parent = parent;
 
-       /* now do the debugfs renaming to reattach the child
-          to the proper parent */
-
        return 0;
 }
 
@@ -665,89 +681,6 @@ static int __init clk_syscore_init(void)
 subsys_initcall(clk_syscore_init);
 #endif
 
-/*
- *     debugfs support to trace clock tree hierarchy and attributes
- */
-static struct dentry *clk_debugfs_root;
-
-static int clk_debugfs_register_one(struct clk *c)
-{
-       int err;
-       struct dentry *d;
-       struct clk *pa = c->parent;
-       char s[255];
-       char *p = s;
-
-       p += sprintf(p, "%p", c);
-       d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root);
-       if (!d)
-               return -ENOMEM;
-       c->dentry = d;
-
-       d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags);
-       if (!d) {
-               err = -ENOMEM;
-               goto err_out;
-       }
-       return 0;
-
-err_out:
-       debugfs_remove_recursive(c->dentry);
-       return err;
-}
-
-static int clk_debugfs_register(struct clk *c)
-{
-       int err;
-       struct clk *pa = c->parent;
-
-       if (pa && !pa->dentry) {
-               err = clk_debugfs_register(pa);
-               if (err)
-                       return err;
-       }
-
-       if (!c->dentry) {
-               err = clk_debugfs_register_one(c);
-               if (err)
-                       return err;
-       }
-       return 0;
-}
-
-static int __init clk_debugfs_init(void)
-{
-       struct clk *c;
-       struct dentry *d;
-       int err;
-
-       d = debugfs_create_dir("clock", NULL);
-       if (!d)
-               return -ENOMEM;
-       clk_debugfs_root = d;
-
-       list_for_each_entry(c, &clock_list, node) {
-               err = clk_debugfs_register(c);
-               if (err)
-                       goto err_out;
-       }
-       return 0;
-err_out:
-       debugfs_remove_recursive(clk_debugfs_root);
-       return err;
-}
-late_initcall(clk_debugfs_init);
-
 static int __init clk_late_init(void)
 {
        unsigned long flags;
diff --git a/drivers/sh/pm_runtime.c b/drivers/sh/pm_runtime.c
new file mode 100644 (file)
index 0000000..afe9282
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Runtime PM support code
+ *
+ *  Copyright (C) 2009-2010 Magnus Damm
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_domain.h>
+#include <linux/pm_clock.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/sh_clk.h>
+#include <linux/bitmap.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_PM_RUNTIME
+
+static int default_platform_runtime_idle(struct device *dev)
+{
+       /* suspend synchronously to disable clocks immediately */
+       return pm_runtime_suspend(dev);
+}
+
+static struct dev_pm_domain default_pm_domain = {
+       .ops = {
+               .runtime_suspend = pm_clk_suspend,
+               .runtime_resume = pm_clk_resume,
+               .runtime_idle = default_platform_runtime_idle,
+               USE_PLATFORM_PM_SLEEP_OPS
+       },
+};
+
+#define DEFAULT_PM_DOMAIN_PTR  (&default_pm_domain)
+
+#else
+
+#define DEFAULT_PM_DOMAIN_PTR  NULL
+
+#endif /* CONFIG_PM_RUNTIME */
+
+static struct pm_clk_notifier_block platform_bus_notifier = {
+       .pm_domain = DEFAULT_PM_DOMAIN_PTR,
+       .con_ids = { NULL, },
+};
+
+static int __init sh_pm_runtime_init(void)
+{
+       pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+       return 0;
+}
+core_initcall(sh_pm_runtime_init);
+
+static int __init sh_pm_runtime_late_init(void)
+{
+       pm_genpd_poweroff_unused();
+       return 0;
+}
+late_initcall(sh_pm_runtime_late_init);
index 79665e2..16d6a83 100644 (file)
@@ -907,7 +907,7 @@ static void atmel_spi_cleanup(struct spi_device *spi)
 
 /*-------------------------------------------------------------------------*/
 
-static int __init atmel_spi_probe(struct platform_device *pdev)
+static int __devinit atmel_spi_probe(struct platform_device *pdev)
 {
        struct resource         *regs;
        int                     irq;
@@ -1003,7 +1003,7 @@ out_free:
        return ret;
 }
 
-static int __exit atmel_spi_remove(struct platform_device *pdev)
+static int __devexit atmel_spi_remove(struct platform_device *pdev)
 {
        struct spi_master       *master = platform_get_drvdata(pdev);
        struct atmel_spi        *as = spi_master_get_devdata(master);
@@ -1072,6 +1072,7 @@ static struct platform_driver atmel_spi_driver = {
        },
        .suspend        = atmel_spi_suspend,
        .resume         = atmel_spi_resume,
+       .probe          = atmel_spi_probe,
        .remove         = __exit_p(atmel_spi_remove),
 };
 module_platform_driver(atmel_spi_driver);
index e763254..21c70b2 100644 (file)
@@ -426,7 +426,7 @@ static int __devinit nuc900_spi_probe(struct platform_device *pdev)
                goto err_clk;
        }
 
-       mfp_set_groupg(&pdev->dev);
+       mfp_set_groupg(&pdev->dev, NULL);
        nuc900_init_spi(hw);
 
        err = spi_bitbang_start(&hw->bitbang);
index f103e47..5559b22 100644 (file)
@@ -2184,6 +2184,12 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
                goto  err_clk_prep;
        }
 
+       status = clk_enable(pl022->clk);
+       if (status) {
+               dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
+               goto err_no_clk_en;
+       }
+
        /* Disable SSP */
        writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
               SSP_CR1(pl022->virtbase));
@@ -2237,6 +2243,8 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 
        free_irq(adev->irq[0], pl022);
  err_no_irq:
+       clk_disable(pl022->clk);
+ err_no_clk_en:
        clk_unprepare(pl022->clk);
  err_clk_prep:
        clk_put(pl022->clk);
index 9e1864c..8190f2a 100644 (file)
@@ -1,6 +1,7 @@
 config ET131X
        tristate "Agere ET-1310 Gigabit Ethernet support"
-       depends on PCI
+       depends on PCI && NET && NETDEVICES
+       select PHYLIB
        default n
        ---help---
          This driver supports Agere ET-1310 ethernet adapters.
index f5f44a0..0c1c6ca 100644 (file)
@@ -4469,6 +4469,12 @@ static int et131x_resume(struct device *dev)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume);
+#define ET131X_PM_OPS (&et131x_pm_ops)
+#else
+#define ET131X_PM_OPS NULL
+#endif
+
 /* ISR functions */
 
 /**
@@ -5470,12 +5476,6 @@ err_out:
        return result;
 }
 
-static SIMPLE_DEV_PM_OPS(et131x_pm_ops, et131x_suspend, et131x_resume);
-#define ET131X_PM_OPS (&et131x_pm_ops)
-#else
-#define ET131X_PM_OPS NULL
-#endif
-
 static DEFINE_PCI_DEVICE_TABLE(et131x_pci_table) = {
        { PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_GIG), 0UL},
        { PCI_VDEVICE(ATT, ET131X_PCI_DEVICE_ID_FAST), 0UL},
index 326e967..aec9311 100644 (file)
@@ -242,19 +242,26 @@ static const struct file_operations iio_event_chrdev_fileops = {
 
 static int iio_event_getfd(struct iio_dev *indio_dev)
 {
-       if (indio_dev->event_interface == NULL)
+       struct iio_event_interface *ev_int = indio_dev->event_interface;
+       int fd;
+
+       if (ev_int == NULL)
                return -ENODEV;
 
-       mutex_lock(&indio_dev->event_interface->event_list_lock);
-       if (test_and_set_bit(IIO_BUSY_BIT_POS,
-                            &indio_dev->event_interface->flags)) {
-               mutex_unlock(&indio_dev->event_interface->event_list_lock);
+       mutex_lock(&ev_int->event_list_lock);
+       if (test_and_set_bit(IIO_BUSY_BIT_POS, &ev_int->flags)) {
+               mutex_unlock(&ev_int->event_list_lock);
                return -EBUSY;
        }
-       mutex_unlock(&indio_dev->event_interface->event_list_lock);
-       return anon_inode_getfd("iio:event",
-                               &iio_event_chrdev_fileops,
-                               indio_dev->event_interface, O_RDONLY);
+       mutex_unlock(&ev_int->event_list_lock);
+       fd = anon_inode_getfd("iio:event",
+                               &iio_event_chrdev_fileops, ev_int, O_RDONLY);
+       if (fd < 0) {
+               mutex_lock(&ev_int->event_list_lock);
+               clear_bit(IIO_BUSY_BIT_POS, &ev_int->flags);
+               mutex_unlock(&ev_int->event_list_lock);
+       }
+       return fd;
 }
 
 static int __init iio_init(void)
index d335c7d..828526d 100644 (file)
@@ -32,8 +32,8 @@
 #include "as102_fw.h"
 #include "dvbdev.h"
 
-int debug;
-module_param_named(debug, debug, int, 0644);
+int as102_debug;
+module_param_named(debug, as102_debug, int, 0644);
 MODULE_PARM_DESC(debug, "Turn on/off debugging (default: off)");
 
 int dual_tuner;
index bcda635..fd33f5a 100644 (file)
@@ -37,7 +37,8 @@ extern struct spi_driver as102_spi_driver;
 #define DRIVER_FULL_NAME "Abilis Systems as10x usb driver"
 #define DRIVER_NAME "as10x_usb"
 
-extern int debug;
+extern int as102_debug;
+#define debug  as102_debug
 
 #define dprintk(debug, args...) \
        do { if (debug) {       \
index b445cd6..2542c37 100644 (file)
@@ -275,7 +275,7 @@ int cvm_oct_xmit(struct sk_buff *skb, struct net_device *dev)
                CVM_OCT_SKB_CB(skb)[0] = hw_buffer.u64;
                for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                        struct skb_frag_struct *fs = skb_shinfo(skb)->frags + i;
-                       hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page) + fs->page_offset));
+                       hw_buffer.s.addr = XKPHYS_TO_PHYS((u64)(page_address(fs->page.p) + fs->page_offset));
                        hw_buffer.s.size = fs->size;
                        CVM_OCT_SKB_CB(skb)[i + 1] = hw_buffer.u64;
                }
index 5cde96b..5c2a15b 100644 (file)
@@ -1,6 +1,6 @@
 config SLICOSS
        tristate "Alacritech Gigabit IS-NIC support"
-       depends on PCI && X86
+       depends on PCI && X86 && NET
        default n
        help
          This driver supports Alacritech's IS-NIC gigabit ethernet cards.
index 435f6fa..44fbeba 100644 (file)
@@ -46,6 +46,7 @@ static inline char __dcc_getchar(void)
 
        asm volatile("mrc p14, 0, %0, c0, c5, 0 @ read comms data reg"
                : "=r" (__c));
+       isb();
 
        return __c;
 }
@@ -55,6 +56,7 @@ static inline void __dcc_putchar(char c)
        asm volatile("mcr p14, 0, %0, c0, c5, 0 @ write a char"
                : /* no output register */
                : "r" (c));
+       isb();
 }
 
 static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
index 4cb0d0a..fc7bbba 100644 (file)
 static int debug;
 module_param(debug, int, 0600);
 
-#define T1     (HZ/10)
-#define T2     (HZ/3)
-#define N2     3
+/* Defaults: these are from the specification */
+
+#define T1     10              /* 100mS */
+#define T2     34              /* 333mS */
+#define N2     3               /* Retry 3 times */
 
 /* Use long timers for testing at low speed with debug on */
 #ifdef DEBUG_TIMING
-#define T1     HZ
-#define T2     (2 * HZ)
+#define T1     100
+#define T2     200
 #endif
 
 /*
index 5f479da..925a1e5 100644 (file)
@@ -1560,7 +1560,7 @@ config SERIAL_IFX6X60
          Support for the IFX6x60 modem devices on Intel MID platforms.
 
 config SERIAL_PCH_UART
-       tristate "Intel EG20T PCH / OKI SEMICONDUCTOR IOH(ML7213/ML7223) UART"
+       tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) UART"
        depends on PCI
        select SERIAL_CORE
        help
@@ -1568,12 +1568,12 @@ config SERIAL_PCH_UART
          which is an IOH(Input/Output Hub) for x86 embedded processor.
          Enabling PCH_DMA, this PCH UART works as DMA mode.
 
-         This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
-         Output Hub), ML7213 and ML7223.
-         ML7213 IOH is for IVI(In-Vehicle Infotainment) use and ML7223 IOH is
-         for MP(Media Phone) use.
-         ML7213/ML7223 is companion chip for Intel Atom E6xx series.
-         ML7213/ML7223 is completely compatible for Intel EG20T PCH.
+         This driver also can be used for LAPIS Semiconductor IOH(Input/
+         Output Hub), ML7213, ML7223 and ML7831.
+         ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is
+         for MP(Media Phone) use and ML7831 IOH is for general purpose use.
+         ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH.
 
 config SERIAL_MSM_SMD
        bool "Enable tty device interface for some SMD ports"
index 4a0f86f..4c823f3 100644 (file)
@@ -228,7 +228,7 @@ void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf)
        if (rs485conf->flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
                atmel_port->tx_done_mask = ATMEL_US_TXEMPTY;
-               if (rs485conf->flags & SER_RS485_RTS_AFTER_SEND)
+               if ((rs485conf->delay_rts_after_send) > 0)
                        UART_PUT_TTGR(port, rs485conf->delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
        } else {
@@ -304,7 +304,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl)
 
        if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
-               if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+               if ((atmel_port->rs485.delay_rts_after_send) > 0)
                        UART_PUT_TTGR(port,
                                        atmel_port->rs485.delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
@@ -1228,7 +1228,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
        if (atmel_port->rs485.flags & SER_RS485_ENABLED) {
                dev_dbg(port->dev, "Setting UART to RS485\n");
-               if (atmel_port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
+               if ((atmel_port->rs485.delay_rts_after_send) > 0)
                        UART_PUT_TTGR(port,
                                        atmel_port->rs485.delay_rts_after_send);
                mode |= ATMEL_US_USMODE_RS485;
@@ -1447,16 +1447,6 @@ static void __devinit atmel_of_init_port(struct atmel_uart_port *atmel_port,
                rs485conf->delay_rts_after_send = rs485_delay[1];
                rs485conf->flags = 0;
 
-               if (rs485conf->delay_rts_before_send == 0 &&
-                   rs485conf->delay_rts_after_send == 0) {
-                       rs485conf->flags |= SER_RS485_RTS_ON_SEND;
-               } else {
-                       if (rs485conf->delay_rts_before_send)
-                               rs485conf->flags |= SER_RS485_RTS_BEFORE_SEND;
-                       if (rs485conf->delay_rts_after_send)
-                               rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
-               }
-
                if (of_get_property(np, "rs485-rx-during-tx", NULL))
                        rs485conf->flags |= SER_RS485_RX_DURING_TX;
 
index b743504..1dfba7b 100644 (file)
@@ -3234,9 +3234,8 @@ rs_write(struct tty_struct *tty,
                e100_disable_rx(info);
                e100_enable_rx_irq(info);
 #endif
-               if ((info->rs485.flags & SER_RS485_RTS_BEFORE_SEND) &&
-                       (info->rs485.delay_rts_before_send > 0))
-                               msleep(info->rs485.delay_rts_before_send);
+               if (info->rs485.delay_rts_before_send > 0)
+                       msleep(info->rs485.delay_rts_before_send);
        }
 #endif /* CONFIG_ETRAX_RS485 */
 
@@ -3693,10 +3692,6 @@ rs_ioctl(struct tty_struct *tty,
 
                rs485data.delay_rts_before_send = rs485ctrl.delay_rts_before_send;
                rs485data.flags = 0;
-               if (rs485data.delay_rts_before_send != 0)
-                       rs485data.flags |= SER_RS485_RTS_BEFORE_SEND;
-               else
-                       rs485data.flags &= ~(SER_RS485_RTS_BEFORE_SEND);
 
                if (rs485ctrl.enabled)
                        rs485data.flags |= SER_RS485_ENABLED;
@@ -4531,7 +4526,6 @@ static int __init rs_init(void)
                /* Set sane defaults */
                info->rs485.flags &= ~(SER_RS485_RTS_ON_SEND);
                info->rs485.flags |= SER_RS485_RTS_AFTER_SEND;
-               info->rs485.flags &= ~(SER_RS485_RTS_BEFORE_SEND);
                info->rs485.delay_rts_before_send = 0;
                info->rs485.flags &= ~(SER_RS485_ENABLED);
 #endif
index 286c386..e272d39 100644 (file)
@@ -884,7 +884,6 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
 {
        struct uart_hsu_port *up =
                        container_of(port, struct uart_hsu_port, port);
-       struct tty_struct *tty = port->state->port.tty;
        unsigned char cval, fcr = 0;
        unsigned long flags;
        unsigned int baud, quot;
@@ -907,8 +906,7 @@ serial_hsu_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 
        /* CMSPAR isn't supported by this driver */
-       if (tty)
-               tty->termios->c_cflag &= ~CMSPAR;
+       termios->c_cflag &= ~CMSPAR;
 
        if (termios->c_cflag & CSTOPB)
                cval |= UART_LCR_STOP;
index 21febef..d6aba8c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
  *
  *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
@@ -46,8 +46,8 @@ enum {
 
 /* Set the max number of UART port
  * Intel EG20T PCH: 4 port
- * OKI SEMICONDUCTOR ML7213 IOH: 3 port
- * OKI SEMICONDUCTOR ML7223 IOH: 2 port
+ * LAPIS Semiconductor ML7213 IOH: 3 port
+ * LAPIS Semiconductor ML7223 IOH: 2 port
 */
 #define PCH_UART_NR    4
 
@@ -258,6 +258,8 @@ enum pch_uart_num_t {
        pch_ml7213_uart2,
        pch_ml7223_uart0,
        pch_ml7223_uart1,
+       pch_ml7831_uart0,
+       pch_ml7831_uart1,
 };
 
 static struct pch_uart_driver_data drv_dat[] = {
@@ -270,6 +272,8 @@ static struct pch_uart_driver_data drv_dat[] = {
        [pch_ml7213_uart2] = {PCH_UART_2LINE, 2},
        [pch_ml7223_uart0] = {PCH_UART_8LINE, 0},
        [pch_ml7223_uart1] = {PCH_UART_2LINE, 1},
+       [pch_ml7831_uart0] = {PCH_UART_8LINE, 0},
+       [pch_ml7831_uart1] = {PCH_UART_2LINE, 1},
 };
 
 static unsigned int default_baud = 9600;
@@ -628,6 +632,7 @@ static void pch_request_dma(struct uart_port *port)
                dev_err(priv->port.dev, "%s:dma_request_channel FAILS(Rx)\n",
                        __func__);
                dma_release_channel(priv->chan_tx);
+               priv->chan_tx = NULL;
                return;
        }
 
@@ -1215,8 +1220,7 @@ static void pch_uart_shutdown(struct uart_port *port)
                dev_err(priv->port.dev,
                        "pch_uart_hal_set_fifo Failed(ret=%d)\n", ret);
 
-       if (priv->use_dma_flag)
-               pch_free_dma(port);
+       pch_free_dma(port);
 
        free_irq(priv->port.irq, priv);
 }
@@ -1280,6 +1284,7 @@ static void pch_uart_set_termios(struct uart_port *port,
        if (rtn)
                goto out;
 
+       pch_uart_set_mctrl(&priv->port, priv->port.mctrl);
        /* Don't rewrite B0 */
        if (tty_termios_baud_rate(termios))
                tty_termios_encode_baud_rate(termios, baud, baud);
@@ -1552,6 +1557,10 @@ static DEFINE_PCI_DEVICE_TABLE(pch_uart_pci_id) = {
         .driver_data = pch_ml7223_uart0},
        {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x800D),
         .driver_data = pch_ml7223_uart1},
+       {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8811),
+        .driver_data = pch_ml7831_uart0},
+       {PCI_DEVICE(PCI_VENDOR_ID_ROHM, 0x8812),
+        .driver_data = pch_ml7831_uart1},
        {0,},
 };
 
index 1945c70..aff9d61 100644 (file)
@@ -206,6 +206,25 @@ static struct plat_sci_reg sci_regmap[SCIx_NR_REGTYPES][SCIx_NR_REGS] = {
                [SCLSR]         = sci_reg_invalid,
        },
 
+       /*
+        * Common SH-2(A) SCIF definitions for ports with FIFO data
+        * count registers.
+        */
+       [SCIx_SH2_SCIF_FIFODATA_REGTYPE] = {
+               [SCSMR]         = { 0x00, 16 },
+               [SCBRR]         = { 0x04,  8 },
+               [SCSCR]         = { 0x08, 16 },
+               [SCxTDR]        = { 0x0c,  8 },
+               [SCxSR]         = { 0x10, 16 },
+               [SCxRDR]        = { 0x14,  8 },
+               [SCFCR]         = { 0x18, 16 },
+               [SCFDR]         = { 0x1c, 16 },
+               [SCTFDR]        = sci_reg_invalid,
+               [SCRFDR]        = sci_reg_invalid,
+               [SCSPTR]        = { 0x20, 16 },
+               [SCLSR]         = { 0x24, 16 },
+       },
+
        /*
         * Common SH-3 SCIF definitions.
         */
index 512c49f..8e0924f 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <linux/kmod.h>
 #include <linux/nsproxy.h>
+#include <linux/ratelimit.h>
 
 /*
  *     This guards the refcounted line discipline lists. The lock
@@ -547,15 +548,16 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
 /**
  *     tty_ldisc_wait_idle     -       wait for the ldisc to become idle
  *     @tty: tty to wait for
+ *     @timeout: for how long to wait at most
  *
  *     Wait for the line discipline to become idle. The discipline must
  *     have been halted for this to guarantee it remains idle.
  */
-static int tty_ldisc_wait_idle(struct tty_struct *tty)
+static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout)
 {
-       int ret;
+       long ret;
        ret = wait_event_timeout(tty_ldisc_idle,
-                       atomic_read(&tty->ldisc->users) == 1, 5 * HZ);
+                       atomic_read(&tty->ldisc->users) == 1, timeout);
        if (ret < 0)
                return ret;
        return ret > 0 ? 0 : -EBUSY;
@@ -665,7 +667,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
 
        tty_ldisc_flush_works(tty);
 
-       retval = tty_ldisc_wait_idle(tty);
+       retval = tty_ldisc_wait_idle(tty, 5 * HZ);
 
        tty_lock();
        mutex_lock(&tty->ldisc_mutex);
@@ -762,8 +764,6 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
        if (IS_ERR(ld))
                return -1;
 
-       WARN_ON_ONCE(tty_ldisc_wait_idle(tty));
-
        tty_ldisc_close(tty, tty->ldisc);
        tty_ldisc_put(tty->ldisc);
        tty->ldisc = NULL;
@@ -838,7 +838,7 @@ void tty_ldisc_hangup(struct tty_struct *tty)
        tty_unlock();
        cancel_work_sync(&tty->buf.work);
        mutex_unlock(&tty->ldisc_mutex);
-
+retry:
        tty_lock();
        mutex_lock(&tty->ldisc_mutex);
 
@@ -847,6 +847,22 @@ void tty_ldisc_hangup(struct tty_struct *tty)
           it means auditing a lot of other paths so this is
           a FIXME */
        if (tty->ldisc) {       /* Not yet closed */
+               if (atomic_read(&tty->ldisc->users) != 1) {
+                       char cur_n[TASK_COMM_LEN], tty_n[64];
+                       long timeout = 3 * HZ;
+                       tty_unlock();
+
+                       while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) {
+                               timeout = MAX_SCHEDULE_TIMEOUT;
+                               printk_ratelimited(KERN_WARNING
+                                       "%s: waiting (%s) for %s took too long, but we keep waiting...\n",
+                                       __func__, get_task_comm(cur_n, current),
+                                       tty_name(tty, tty_n));
+                       }
+                       mutex_unlock(&tty->ldisc_mutex);
+                       goto retry;
+               }
+
                if (reset == 0) {
 
                        if (!tty_ldisc_reinit(tty, tty->termios->c_line))
index 6960715..e8c564a 100644 (file)
@@ -539,7 +539,6 @@ static void acm_port_down(struct acm *acm)
 {
        int i;
 
-       mutex_lock(&open_mutex);
        if (acm->dev) {
                usb_autopm_get_interface(acm->control);
                acm_set_control(acm, acm->ctrlout = 0);
@@ -551,14 +550,15 @@ static void acm_port_down(struct acm *acm)
                acm->control->needs_remote_wakeup = 0;
                usb_autopm_put_interface(acm->control);
        }
-       mutex_unlock(&open_mutex);
 }
 
 static void acm_tty_hangup(struct tty_struct *tty)
 {
        struct acm *acm = tty->driver_data;
        tty_port_hangup(&acm->port);
+       mutex_lock(&open_mutex);
        acm_port_down(acm);
+       mutex_unlock(&open_mutex);
 }
 
 static void acm_tty_close(struct tty_struct *tty, struct file *filp)
@@ -569,8 +569,9 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
           shutdown */
        if (!acm)
                return;
+
+       mutex_lock(&open_mutex);
        if (tty_port_close_start(&acm->port, tty, filp) == 0) {
-               mutex_lock(&open_mutex);
                if (!acm->dev) {
                        tty_port_tty_set(&acm->port, NULL);
                        acm_tty_unregister(acm);
@@ -582,6 +583,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp)
        acm_port_down(acm);
        tty_port_close_end(&acm->port, tty);
        tty_port_tty_set(&acm->port, NULL);
+       mutex_unlock(&open_mutex);
 }
 
 static int acm_tty_write(struct tty_struct *tty,
index 96f05b2..7978146 100644 (file)
@@ -813,6 +813,12 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                                        USB_PORT_FEAT_C_PORT_LINK_STATE);
                }
 
+               if ((portchange & USB_PORT_STAT_C_BH_RESET) &&
+                               hub_is_superspeed(hub->hdev)) {
+                       need_debounce_delay = true;
+                       clear_port_feature(hub->hdev, port1,
+                                       USB_PORT_FEAT_C_BH_PORT_RESET);
+               }
                /* We can forget about a "removed" device when there's a
                 * physical disconnect or the connect status changes.
                 */
index d6a8d82..ecf12e1 100644 (file)
@@ -50,15 +50,42 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Logitech Webcam B/C500 */
        { USB_DEVICE(0x046d, 0x0807), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech Webcam C600 */
+       { USB_DEVICE(0x046d, 0x0808), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Webcam Pro 9000 */
        { USB_DEVICE(0x046d, 0x0809), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech Webcam C905 */
+       { USB_DEVICE(0x046d, 0x080a), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Webcam C210 */
+       { USB_DEVICE(0x046d, 0x0819), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Webcam C260 */
+       { USB_DEVICE(0x046d, 0x081a), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Webcam C310 */
        { USB_DEVICE(0x046d, 0x081b), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech Webcam C910 */
+       { USB_DEVICE(0x046d, 0x0821), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Webcam C160 */
+       { USB_DEVICE(0x046d, 0x0824), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Webcam C270 */
        { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Logitech Quickcam Pro 9000 */
+       { USB_DEVICE(0x046d, 0x0990), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Quickcam E3500 */
+       { USB_DEVICE(0x046d, 0x09a4), .driver_info = USB_QUIRK_RESET_RESUME },
+
+       /* Logitech Quickcam Vision Pro */
+       { USB_DEVICE(0x046d, 0x09a6), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech Harmony 700-series */
        { USB_DEVICE(0x046d, 0xc122), .driver_info = USB_QUIRK_DELAY_INIT },
 
index fa824cf..25dbd86 100644 (file)
@@ -1284,6 +1284,7 @@ static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc)
                        int             ret;
 
                        dep->endpoint.maxpacket = 1024;
+                       dep->endpoint.max_streams = 15;
                        dep->endpoint.ops = &dwc3_gadget_ep_ops;
                        list_add_tail(&dep->endpoint.ep_list,
                                        &dwc->gadget.ep_list);
index b21cd37..23a4473 100644 (file)
@@ -469,7 +469,7 @@ config USB_LANGWELL
           gadget drivers to also be dynamically linked.
 
 config USB_EG20T
-       tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH UDC"
+       tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC"
        depends on PCI
        select USB_GADGET_DUALSPEED
        help
@@ -485,10 +485,11 @@ config USB_EG20T
          This driver dose not support interrupt transfer or isochronous
          transfer modes.
 
-         This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is
+         This driver also can be used for LAPIS Semiconductor's ML7213 which is
          for IVI(In-Vehicle Infotainment) use.
-         ML7213 is companion chip for Intel Atom E6xx series.
-         ML7213 is completely compatible for Intel EG20T PCH.
+         ML7831 is for general purpose use.
+         ML7213/ML7831 is companion chip for Intel Atom E6xx series.
+         ML7213/ML7831 is completely compatible for Intel EG20T PCH.
 
 config USB_CI13XXX_MSM
        tristate "MIPS USB CI13xxx for MSM"
index 4eedfe5..1fc6129 100644 (file)
@@ -122,3 +122,5 @@ static int __init ci13xxx_msm_init(void)
        return platform_driver_register(&ci13xxx_msm_driver);
 }
 module_init(ci13xxx_msm_init);
+
+MODULE_LICENSE("GPL v2");
index 83428f5..9a0c397 100644 (file)
@@ -71,6 +71,9 @@
 /******************************************************************************
  * DEFINE
  *****************************************************************************/
+
+#define DMA_ADDR_INVALID       (~(dma_addr_t)0)
+
 /* ctrl register bank access */
 static DEFINE_SPINLOCK(udc_lock);
 
@@ -1434,7 +1437,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
                return -EALREADY;
 
        mReq->req.status = -EALREADY;
-       if (length && !mReq->req.dma) {
+       if (length && mReq->req.dma == DMA_ADDR_INVALID) {
                mReq->req.dma = \
                        dma_map_single(mEp->device, mReq->req.buf,
                                       length, mEp->dir ? DMA_TO_DEVICE :
@@ -1453,7 +1456,7 @@ static int _hardware_enqueue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
                                dma_unmap_single(mEp->device, mReq->req.dma,
                                        length, mEp->dir ? DMA_TO_DEVICE :
                                        DMA_FROM_DEVICE);
-                               mReq->req.dma = 0;
+                               mReq->req.dma = DMA_ADDR_INVALID;
                                mReq->map     = 0;
                        }
                        return -ENOMEM;
@@ -1549,7 +1552,7 @@ static int _hardware_dequeue(struct ci13xxx_ep *mEp, struct ci13xxx_req *mReq)
        if (mReq->map) {
                dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
                                 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               mReq->req.dma = 0;
+               mReq->req.dma = DMA_ADDR_INVALID;
                mReq->map     = 0;
        }
 
@@ -1610,7 +1613,6 @@ __acquires(mEp->lock)
  * @gadget: gadget
  *
  * This function returns an error code
- * Caller must hold lock
  */
 static int _gadget_stop_activity(struct usb_gadget *gadget)
 {
@@ -2189,6 +2191,7 @@ static struct usb_request *ep_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
        mReq = kzalloc(sizeof(struct ci13xxx_req), gfp_flags);
        if (mReq != NULL) {
                INIT_LIST_HEAD(&mReq->queue);
+               mReq->req.dma = DMA_ADDR_INVALID;
 
                mReq->ptr = dma_pool_alloc(mEp->td_pool, gfp_flags,
                                           &mReq->dma);
@@ -2328,7 +2331,7 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
        if (mReq->map) {
                dma_unmap_single(mEp->device, mReq->req.dma, mReq->req.length,
                                 mEp->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
-               mReq->req.dma = 0;
+               mReq->req.dma = DMA_ADDR_INVALID;
                mReq->map     = 0;
        }
        req->status = -ECONNRESET;
@@ -2500,12 +2503,12 @@ static int ci13xxx_wakeup(struct usb_gadget *_gadget)
        spin_lock_irqsave(udc->lock, flags);
        if (!udc->remote_wakeup) {
                ret = -EOPNOTSUPP;
-               dbg_trace("remote wakeup feature is not enabled\n");
+               trace("remote wakeup feature is not enabled\n");
                goto out;
        }
        if (!hw_cread(CAP_PORTSC, PORTSC_SUSP)) {
                ret = -EINVAL;
-               dbg_trace("port is not suspended\n");
+               trace("port is not suspended\n");
                goto out;
        }
        hw_cwrite(CAP_PORTSC, PORTSC_FPR, PORTSC_FPR);
@@ -2703,7 +2706,9 @@ static int ci13xxx_stop(struct usb_gadget_driver *driver)
                if (udc->udc_driver->notify_event)
                        udc->udc_driver->notify_event(udc,
                        CI13XXX_CONTROLLER_STOPPED_EVENT);
+               spin_unlock_irqrestore(udc->lock, flags);
                _gadget_stop_activity(&udc->gadget);
+               spin_lock_irqsave(udc->lock, flags);
                pm_runtime_put(&udc->gadget.dev);
        }
 
@@ -2850,7 +2855,7 @@ static int udc_probe(struct ci13xxx_udc_driver *driver, struct device *dev,
        struct ci13xxx *udc;
        int retval = 0;
 
-       trace("%p, %p, %p", dev, regs, name);
+       trace("%p, %p, %p", dev, regs, driver->name);
 
        if (dev == NULL || regs == NULL || driver == NULL ||
                        driver->name == NULL)
index 52583a2..c39d588 100644 (file)
@@ -624,7 +624,8 @@ static int fsg_setup(struct usb_function *f,
                if (ctrl->bRequestType !=
                    (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
                        break;
-               if (w_index != fsg->interface_number || w_value != 0)
+               if (w_index != fsg->interface_number || w_value != 0 ||
+                               w_length != 0)
                        return -EDOM;
 
                /*
@@ -639,7 +640,8 @@ static int fsg_setup(struct usb_function *f,
                if (ctrl->bRequestType !=
                    (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE))
                        break;
-               if (w_index != fsg->interface_number || w_value != 0)
+               if (w_index != fsg->interface_number || w_value != 0 ||
+                               w_length != 1)
                        return -EDOM;
                VDBG(fsg, "get max LUN\n");
                *(u8 *)req->buf = fsg->common->nluns - 1;
index 67b2229..3797b3d 100644 (file)
@@ -95,7 +95,6 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req);
 
 DECLARE_UAC_AC_HEADER_DESCRIPTOR(1);
 DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1);
-DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(16);
 DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16);
 
 /* B.3.1  Standard AC Interface Descriptor */
@@ -140,26 +139,6 @@ static struct usb_ms_header_descriptor ms_header_desc __initdata = {
        /* .wTotalLength =      DYNAMIC */
 };
 
-/* B.4.3  Embedded MIDI IN Jack Descriptor */
-static struct usb_midi_in_jack_descriptor jack_in_emb_desc = {
-       .bLength =            USB_DT_MIDI_IN_SIZE,
-       .bDescriptorType =      USB_DT_CS_INTERFACE,
-       .bDescriptorSubtype =   USB_MS_MIDI_IN_JACK,
-       .bJackType =        USB_MS_EMBEDDED,
-       /* .bJackID =           DYNAMIC */
-};
-
-/* B.4.4  Embedded MIDI OUT Jack Descriptor */
-static struct usb_midi_out_jack_descriptor_16 jack_out_emb_desc = {
-       /* .bLength =           DYNAMIC */
-       .bDescriptorType =      USB_DT_CS_INTERFACE,
-       .bDescriptorSubtype =   USB_MS_MIDI_OUT_JACK,
-       .bJackType =            USB_MS_EMBEDDED,
-       /* .bJackID =           DYNAMIC */
-       /* .bNrInputPins =      DYNAMIC */
-       /* .pins =              DYNAMIC */
-};
-
 /* B.5.1  Standard Bulk OUT Endpoint Descriptor */
 static struct usb_endpoint_descriptor bulk_out_desc = {
        .bLength =              USB_DT_ENDPOINT_AUDIO_SIZE,
@@ -758,9 +737,11 @@ fail:
 static int __init
 f_midi_bind(struct usb_configuration *c, struct usb_function *f)
 {
-       struct usb_descriptor_header *midi_function[(MAX_PORTS * 2) + 12];
+       struct usb_descriptor_header **midi_function;
        struct usb_midi_in_jack_descriptor jack_in_ext_desc[MAX_PORTS];
+       struct usb_midi_in_jack_descriptor jack_in_emb_desc[MAX_PORTS];
        struct usb_midi_out_jack_descriptor_1 jack_out_ext_desc[MAX_PORTS];
+       struct usb_midi_out_jack_descriptor_1 jack_out_emb_desc[MAX_PORTS];
        struct usb_composite_dev *cdev = c->cdev;
        struct f_midi *midi = func_to_midi(f);
        int status, n, jack = 1, i = 0;
@@ -798,6 +779,14 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
                goto fail;
        midi->out_ep->driver_data = cdev;       /* claim */
 
+       /* allocate temporary function list */
+       midi_function = kcalloc((MAX_PORTS * 4) + 9, sizeof(midi_function),
+                               GFP_KERNEL);
+       if (!midi_function) {
+               status = -ENOMEM;
+               goto fail;
+       }
+
        /*
         * construct the function's descriptor set. As the number of
         * input and output MIDI ports is configurable, we have to do
@@ -811,73 +800,74 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
 
        /* calculate the header's wTotalLength */
        n = USB_DT_MS_HEADER_SIZE
-               + (1 + midi->in_ports) * USB_DT_MIDI_IN_SIZE
-               + (1 + midi->out_ports) * USB_DT_MIDI_OUT_SIZE(1);
+               + (midi->in_ports + midi->out_ports) *
+                       (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1));
        ms_header_desc.wTotalLength = cpu_to_le16(n);
 
        midi_function[i++] = (struct usb_descriptor_header *) &ms_header_desc;
 
-       /* we have one embedded IN jack */
-       jack_in_emb_desc.bJackID = jack++;
-       midi_function[i++] = (struct usb_descriptor_header *) &jack_in_emb_desc;
-
-       /* and a dynamic amount of external IN jacks */
-       for (n = 0; n < midi->in_ports; n++) {
-               struct usb_midi_in_jack_descriptor *ext = &jack_in_ext_desc[n];
-
-               ext->bLength =                  USB_DT_MIDI_IN_SIZE;
-               ext->bDescriptorType =          USB_DT_CS_INTERFACE;
-               ext->bDescriptorSubtype =       USB_MS_MIDI_IN_JACK;
-               ext->bJackType =                USB_MS_EXTERNAL;
-               ext->bJackID =                  jack++;
-               ext->iJack =                    0;
-
-               midi_function[i++] = (struct usb_descriptor_header *) ext;
-       }
-
-       /* one embedded OUT jack ... */
-       jack_out_emb_desc.bLength = USB_DT_MIDI_OUT_SIZE(midi->in_ports);
-       jack_out_emb_desc.bJackID = jack++;
-       jack_out_emb_desc.bNrInputPins = midi->in_ports;
-       /* ... which referencess all external IN jacks */
+       /* configure the external IN jacks, each linked to an embedded OUT jack */
        for (n = 0; n < midi->in_ports; n++) {
-               jack_out_emb_desc.pins[n].baSourceID = jack_in_ext_desc[n].bJackID;
-               jack_out_emb_desc.pins[n].baSourcePin = 1;
+               struct usb_midi_in_jack_descriptor *in_ext = &jack_in_ext_desc[n];
+               struct usb_midi_out_jack_descriptor_1 *out_emb = &jack_out_emb_desc[n];
+
+               in_ext->bLength                 = USB_DT_MIDI_IN_SIZE;
+               in_ext->bDescriptorType         = USB_DT_CS_INTERFACE;
+               in_ext->bDescriptorSubtype      = USB_MS_MIDI_IN_JACK;
+               in_ext->bJackType               = USB_MS_EXTERNAL;
+               in_ext->bJackID                 = jack++;
+               in_ext->iJack                   = 0;
+               midi_function[i++] = (struct usb_descriptor_header *) in_ext;
+
+               out_emb->bLength                = USB_DT_MIDI_OUT_SIZE(1);
+               out_emb->bDescriptorType        = USB_DT_CS_INTERFACE;
+               out_emb->bDescriptorSubtype     = USB_MS_MIDI_OUT_JACK;
+               out_emb->bJackType              = USB_MS_EMBEDDED;
+               out_emb->bJackID                = jack++;
+               out_emb->bNrInputPins           = 1;
+               out_emb->pins[0].baSourcePin    = 1;
+               out_emb->pins[0].baSourceID     = in_ext->bJackID;
+               out_emb->iJack                  = 0;
+               midi_function[i++] = (struct usb_descriptor_header *) out_emb;
+
+               /* link it to the endpoint */
+               ms_in_desc.baAssocJackID[n] = out_emb->bJackID;
        }
 
-       midi_function[i++] = (struct usb_descriptor_header *) &jack_out_emb_desc;
-
-       /* and multiple external OUT jacks ... */
+       /* configure the external OUT jacks, each linked to an embedded IN jack */
        for (n = 0; n < midi->out_ports; n++) {
-               struct usb_midi_out_jack_descriptor_1 *ext = &jack_out_ext_desc[n];
-               int m;
-
-               ext->bLength =                  USB_DT_MIDI_OUT_SIZE(1);
-               ext->bDescriptorType =          USB_DT_CS_INTERFACE;
-               ext->bDescriptorSubtype =       USB_MS_MIDI_OUT_JACK;
-               ext->bJackType =                USB_MS_EXTERNAL;
-               ext->bJackID =                  jack++;
-               ext->bNrInputPins =             1;
-               ext->iJack =                    0;
-               /* ... which all reference the same embedded IN jack */
-               for (m = 0; m < midi->out_ports; m++) {
-                       ext->pins[m].baSourceID =       jack_in_emb_desc.bJackID;
-                       ext->pins[m].baSourcePin =      1;
-               }
-
-               midi_function[i++] = (struct usb_descriptor_header *) ext;
+               struct usb_midi_in_jack_descriptor *in_emb = &jack_in_emb_desc[n];
+               struct usb_midi_out_jack_descriptor_1 *out_ext = &jack_out_ext_desc[n];
+
+               in_emb->bLength                 = USB_DT_MIDI_IN_SIZE;
+               in_emb->bDescriptorType         = USB_DT_CS_INTERFACE;
+               in_emb->bDescriptorSubtype      = USB_MS_MIDI_IN_JACK;
+               in_emb->bJackType               = USB_MS_EMBEDDED;
+               in_emb->bJackID                 = jack++;
+               in_emb->iJack                   = 0;
+               midi_function[i++] = (struct usb_descriptor_header *) in_emb;
+
+               out_ext->bLength =              USB_DT_MIDI_OUT_SIZE(1);
+               out_ext->bDescriptorType =      USB_DT_CS_INTERFACE;
+               out_ext->bDescriptorSubtype =   USB_MS_MIDI_OUT_JACK;
+               out_ext->bJackType =            USB_MS_EXTERNAL;
+               out_ext->bJackID =              jack++;
+               out_ext->bNrInputPins =         1;
+               out_ext->iJack =                0;
+               out_ext->pins[0].baSourceID =   in_emb->bJackID;
+               out_ext->pins[0].baSourcePin =  1;
+               midi_function[i++] = (struct usb_descriptor_header *) out_ext;
+
+               /* link it to the endpoint */
+               ms_out_desc.baAssocJackID[n] = in_emb->bJackID;
        }
 
        /* configure the endpoint descriptors ... */
        ms_out_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->in_ports);
        ms_out_desc.bNumEmbMIDIJack = midi->in_ports;
-       for (n = 0; n < midi->in_ports; n++)
-               ms_out_desc.baAssocJackID[n] = jack_in_emb_desc.bJackID;
 
        ms_in_desc.bLength = USB_DT_MS_ENDPOINT_SIZE(midi->out_ports);
        ms_in_desc.bNumEmbMIDIJack = midi->out_ports;
-       for (n = 0; n < midi->out_ports; n++)
-               ms_in_desc.baAssocJackID[n] = jack_out_emb_desc.bJackID;
 
        /* ... and add them to the list */
        midi_function[i++] = (struct usb_descriptor_header *) &bulk_out_desc;
@@ -901,6 +891,8 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
                f->descriptors = usb_copy_descriptors(midi_function);
        }
 
+       kfree(midi_function);
+
        return 0;
 
 fail:
index 3490770..16a509a 100644 (file)
@@ -346,7 +346,7 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
                }
 
                skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page,
-                               skb->len == 0, req->actual);
+                               skb->len <= 1, req->actual);
                page = NULL;
 
                if (req->actual < req->length) { /* Last fragment */
index f7e39b0..11b5196 100644 (file)
@@ -859,7 +859,7 @@ static int class_setup_req(struct fsg_dev *fsg,
                        if (ctrl->bRequestType != (USB_DIR_OUT |
                                        USB_TYPE_CLASS | USB_RECIP_INTERFACE))
                                break;
-                       if (w_index != 0 || w_value != 0) {
+                       if (w_index != 0 || w_value != 0 || w_length != 0) {
                                value = -EDOM;
                                break;
                        }
@@ -875,7 +875,7 @@ static int class_setup_req(struct fsg_dev *fsg,
                        if (ctrl->bRequestType != (USB_DIR_IN |
                                        USB_TYPE_CLASS | USB_RECIP_INTERFACE))
                                break;
-                       if (w_index != 0 || w_value != 0) {
+                       if (w_index != 0 || w_value != 0 || w_length != 1) {
                                value = -EDOM;
                                break;
                        }
index b2c44e1..b3b3d83 100644 (file)
@@ -1717,7 +1717,7 @@ static void dtd_complete_irq(struct fsl_udc *udc)
 
 static inline enum usb_device_speed portscx_device_speed(u32 reg)
 {
-       switch (speed & PORTSCX_PORT_SPEED_MASK) {
+       switch (reg & PORTSCX_PORT_SPEED_MASK) {
        case PORTSCX_PORT_SPEED_HIGH:
                return USB_SPEED_HIGH;
        case PORTSCX_PORT_SPEED_FULL:
@@ -2480,8 +2480,7 @@ static int __init fsl_udc_probe(struct platform_device *pdev)
 
 #ifndef CONFIG_ARCH_MXC
        if (pdata->have_sysif_regs)
-               usb_sys_regs = (struct usb_sys_interface *)
-                               ((u32)dr_regs + USB_DR_SYS_OFFSET);
+               usb_sys_regs = (void *)dr_regs + USB_DR_SYS_OFFSET;
 #endif
 
        /* Initialize USB clocks */
index a392ec0..6ccae27 100644 (file)
@@ -1730,8 +1730,9 @@ static void
 gadgetfs_disconnect (struct usb_gadget *gadget)
 {
        struct dev_data         *dev = get_gadget_data (gadget);
+       unsigned long           flags;
 
-       spin_lock (&dev->lock);
+       spin_lock_irqsave (&dev->lock, flags);
        if (dev->state == STATE_DEV_UNCONNECTED)
                goto exit;
        dev->state = STATE_DEV_UNCONNECTED;
@@ -1740,7 +1741,7 @@ gadgetfs_disconnect (struct usb_gadget *gadget)
        next_event (dev, GADGETFS_DISCONNECT);
        ep0_readable (dev);
 exit:
-       spin_unlock (&dev->lock);
+       spin_unlock_irqrestore (&dev->lock, flags);
 }
 
 static void
index 550d6dc..5048a0c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd.
  *
  * 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
@@ -354,6 +354,7 @@ struct pch_udc_dev {
 #define PCI_DEVICE_ID_INTEL_EG20T_UDC  0x8808
 #define PCI_VENDOR_ID_ROHM             0x10DB
 #define PCI_DEVICE_ID_ML7213_IOH_UDC   0x801D
+#define PCI_DEVICE_ID_ML7831_IOH_UDC   0x8808
 
 static const char      ep0_string[] = "ep0in";
 static DEFINE_SPINLOCK(udc_stall_spinlock);    /* stall spin lock */
@@ -2970,6 +2971,11 @@ static DEFINE_PCI_DEVICE_TABLE(pch_udc_pcidev_id) = {
                .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
                .class_mask = 0xffffffff,
        },
+       {
+               PCI_DEVICE(PCI_VENDOR_ID_ROHM, PCI_DEVICE_ID_ML7831_IOH_UDC),
+               .class = (PCI_CLASS_SERIAL_USB << 8) | 0xfe,
+               .class_mask = 0xffffffff,
+       },
        { 0 },
 };
 
@@ -2999,5 +3005,5 @@ static void __exit pch_udc_pci_exit(void)
 module_exit(pch_udc_pci_exit);
 
 MODULE_DESCRIPTION("Intel EG20T USB Device Controller");
-MODULE_AUTHOR("OKI SEMICONDUCTOR, <toshiharu-linux@dsn.okisemi.com>");
+MODULE_AUTHOR("LAPIS Semiconductor, <tomoya-linux@dsn.lapis-semi.com>");
 MODULE_LICENSE("GPL");
index 68a826a..24f84b2 100644 (file)
@@ -1718,6 +1718,8 @@ static void r8a66597_fifo_flush(struct usb_ep *_ep)
        if (list_empty(&ep->queue) && !ep->busy) {
                pipe_stop(ep->r8a66597, ep->pipenum);
                r8a66597_bclr(ep->r8a66597, BCLR, ep->fifoctr);
+               r8a66597_write(ep->r8a66597, ACLRM, ep->pipectr);
+               r8a66597_write(ep->r8a66597, 0, ep->pipectr);
        }
        spin_unlock_irqrestore(&ep->r8a66597->lock, flags);
 }
@@ -1742,7 +1744,6 @@ static int r8a66597_start(struct usb_gadget *gadget,
                struct usb_gadget_driver *driver)
 {
        struct r8a66597 *r8a66597 = gadget_to_r8a66597(gadget);
-       int retval;
 
        if (!driver
                        || driver->speed != USB_SPEED_HIGH
@@ -1752,16 +1753,7 @@ static int r8a66597_start(struct usb_gadget *gadget,
                return -ENODEV;
 
        /* hook up the driver */
-       driver->driver.bus = NULL;
        r8a66597->driver = driver;
-       r8a66597->gadget.dev.driver = &driver->driver;
-
-       retval = device_add(&r8a66597->gadget.dev);
-       if (retval) {
-               dev_err(r8a66597_to_dev(r8a66597), "device_add error (%d)\n",
-                       retval);
-               goto error;
-       }
 
        init_controller(r8a66597);
        r8a66597_bset(r8a66597, VBSE, INTENB0);
@@ -1775,12 +1767,6 @@ static int r8a66597_start(struct usb_gadget *gadget,
        }
 
        return 0;
-
-error:
-       r8a66597->driver = NULL;
-       r8a66597->gadget.dev.driver = NULL;
-
-       return retval;
 }
 
 static int r8a66597_stop(struct usb_gadget *gadget,
@@ -1794,7 +1780,6 @@ static int r8a66597_stop(struct usb_gadget *gadget,
        disable_controller(r8a66597);
        spin_unlock_irqrestore(&r8a66597->lock, flags);
 
-       device_del(&r8a66597->gadget.dev);
        r8a66597->driver = NULL;
        return 0;
 }
@@ -1845,6 +1830,7 @@ static int __exit r8a66597_remove(struct platform_device *pdev)
                clk_put(r8a66597->clk);
        }
 #endif
+       device_unregister(&r8a66597->gadget.dev);
        kfree(r8a66597);
        return 0;
 }
@@ -1924,13 +1910,17 @@ static int __init r8a66597_probe(struct platform_device *pdev)
        r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;
 
        r8a66597->gadget.ops = &r8a66597_gadget_ops;
-       device_initialize(&r8a66597->gadget.dev);
        dev_set_name(&r8a66597->gadget.dev, "gadget");
        r8a66597->gadget.is_dualspeed = 1;
        r8a66597->gadget.dev.parent = &pdev->dev;
        r8a66597->gadget.dev.dma_mask = pdev->dev.dma_mask;
        r8a66597->gadget.dev.release = pdev->dev.release;
        r8a66597->gadget.name = udc_name;
+       ret = device_register(&r8a66597->gadget.dev);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "device_register failed\n");
+               goto clean_up;
+       }
 
        init_timer(&r8a66597->timer);
        r8a66597->timer.function = r8a66597_timer;
@@ -1945,7 +1935,7 @@ static int __init r8a66597_probe(struct platform_device *pdev)
                        dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
                                clk_name);
                        ret = PTR_ERR(r8a66597->clk);
-                       goto clean_up;
+                       goto clean_up_dev;
                }
                clk_enable(r8a66597->clk);
        }
@@ -2014,7 +2004,9 @@ clean_up2:
                clk_disable(r8a66597->clk);
                clk_put(r8a66597->clk);
        }
+clean_up_dev:
 #endif
+       device_unregister(&r8a66597->gadget.dev);
 clean_up:
        if (r8a66597) {
                if (r8a66597->sudmac_reg)
index 022baec..6939e17 100644 (file)
@@ -210,10 +210,10 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
        kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
 
        if (udc_is_newstyle(udc)) {
-               usb_gadget_disconnect(udc->gadget);
+               udc->driver->disconnect(udc->gadget);
                udc->driver->unbind(udc->gadget);
                usb_gadget_udc_stop(udc->gadget, udc->driver);
-
+               usb_gadget_disconnect(udc->gadget);
        } else {
                usb_gadget_stop(udc->gadget, udc->driver);
        }
@@ -344,7 +344,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_unregister_driver);
 static ssize_t usb_udc_srp_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t n)
 {
-       struct usb_udc          *udc = dev_get_drvdata(dev);
+       struct usb_udc          *udc = container_of(dev, struct usb_udc, dev);
 
        if (sysfs_streq(buf, "1"))
                usb_gadget_wakeup(udc->gadget);
@@ -378,7 +378,7 @@ static ssize_t usb_udc_speed_show(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        usb_speed_string(udc->gadget->speed));
 }
-static DEVICE_ATTR(speed, S_IRUSR, usb_udc_speed_show, NULL);
+static DEVICE_ATTR(speed, S_IRUGO, usb_udc_speed_show, NULL);
 
 #define USB_UDC_ATTR(name)                                     \
 ssize_t usb_udc_##name##_show(struct device *dev,              \
@@ -389,7 +389,7 @@ ssize_t usb_udc_##name##_show(struct device *dev,           \
                                                                \
        return snprintf(buf, PAGE_SIZE, "%d\n", gadget->name);  \
 }                                                              \
-static DEVICE_ATTR(name, S_IRUSR, usb_udc_##name##_show, NULL)
+static DEVICE_ATTR(name, S_IRUGO, usb_udc_##name##_show, NULL)
 
 static USB_UDC_ATTR(is_dualspeed);
 static USB_UDC_ATTR(is_otg);
index 2e829fa..56a3203 100644 (file)
@@ -1479,10 +1479,15 @@ iso_stream_schedule (
 
                /* NOTE:  assumes URB_ISO_ASAP, to limit complexity/bugs */
 
-               /* find a uframe slot with enough bandwidth */
-               next = start + period;
-               for (; start < next; start++) {
-
+               /* find a uframe slot with enough bandwidth.
+                * Early uframes are more precious because full-speed
+                * iso IN transfers can't use late uframes,
+                * and therefore they should be allocated last.
+                */
+               next = start;
+               start += period;
+               do {
+                       start--;
                        /* check schedule: enough space? */
                        if (stream->highspeed) {
                                if (itd_slot_ok(ehci, mod, start,
@@ -1495,7 +1500,7 @@ iso_stream_schedule (
                                                start, sched, period))
                                        break;
                        }
-               }
+               } while (start > next);
 
                /* no room in the schedule */
                if (start == next) {
index fe74bd6..b4fb511 100644 (file)
@@ -19,7 +19,7 @@ static int ehci_xls_setup(struct usb_hcd *hcd)
 
        ehci->caps = hcd->regs;
        ehci->regs = hcd->regs +
-               HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+               HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase));
        dbg_hcs_params(ehci, "reset");
        dbg_hcc_params(ehci, "reset");
 
index ba3a46b..95a9fec 100644 (file)
@@ -223,6 +223,9 @@ static void ohci_at91_usb_set_power(struct at91_usbh_data *pdata, int port, int
        if (port < 0 || port >= 2)
                return;
 
+       if (pdata->vbus_pin[port] <= 0)
+               return;
+
        gpio_set_value(pdata->vbus_pin[port], !pdata->vbus_pin_inverted ^ enable);
 }
 
@@ -231,6 +234,9 @@ static int ohci_at91_usb_get_power(struct at91_usbh_data *pdata, int port)
        if (port < 0 || port >= 2)
                return -EINVAL;
 
+       if (pdata->vbus_pin[port] <= 0)
+               return -EINVAL;
+
        return gpio_get_value(pdata->vbus_pin[port]) ^ !pdata->vbus_pin_inverted;
 }
 
index 34efd47..b263919 100644 (file)
@@ -389,17 +389,14 @@ ohci_shutdown (struct usb_hcd *hcd)
        struct ohci_hcd *ohci;
 
        ohci = hcd_to_ohci (hcd);
-       ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable);
-       ohci->hc_control = ohci_readl(ohci, &ohci->regs->control);
+       ohci_writel(ohci, (u32) ~0, &ohci->regs->intrdisable);
 
-       /* If the SHUTDOWN quirk is set, don't put the controller in RESET */
-       ohci->hc_control &= (ohci->flags & OHCI_QUIRK_SHUTDOWN ?
-                       OHCI_CTRL_RWC | OHCI_CTRL_HCFS :
-                       OHCI_CTRL_RWC);
-       ohci_writel(ohci, ohci->hc_control, &ohci->regs->control);
+       /* Software reset, after which the controller goes into SUSPEND */
+       ohci_writel(ohci, OHCI_HCR, &ohci->regs->cmdstatus);
+       ohci_readl(ohci, &ohci->regs->cmdstatus);       /* flush the writes */
+       udelay(10);
 
-       /* flush the writes */
-       (void) ohci_readl (ohci, &ohci->regs->control);
+       ohci_writel(ohci, ohci->fminterval, &ohci->regs->fminterval);
 }
 
 static int check_ed(struct ohci_hcd *ohci, struct ed *ed)
index ad8166c..bc01b06 100644 (file)
@@ -175,28 +175,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
        return 0;
 }
 
-/* nVidia controllers continue to drive Reset signalling on the bus
- * even after system shutdown, wasting power.  This flag tells the
- * shutdown routine to leave the controller OPERATIONAL instead of RESET.
- */
-static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
-{
-       struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
-       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
-
-       /* Evidently nVidia fixed their later hardware; this is a guess at
-        * the changeover point.
-        */
-#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB          0x026d
-
-       if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
-               ohci->flags |= OHCI_QUIRK_SHUTDOWN;
-               ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
-       }
-
-       return 0;
-}
-
 static void sb800_prefetch(struct ohci_hcd *ohci, int on)
 {
        struct pci_dev *pdev;
@@ -260,10 +238,6 @@ static const struct pci_device_id ohci_pci_quirks[] = {
                PCI_DEVICE(PCI_VENDOR_ID_ATI, 0x4399),
                .driver_data = (unsigned long)ohci_quirk_amd700,
        },
-       {
-               PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
-               .driver_data = (unsigned long) ohci_quirk_nvidia_shutdown,
-       },
 
        /* FIXME for some of the early AMD 760 southbridges, OHCI
         * won't work at all.  blacklist them.
index 35e5fd6..0795b93 100644 (file)
@@ -403,7 +403,6 @@ struct ohci_hcd {
 #define        OHCI_QUIRK_HUB_POWER    0x100                   /* distrust firmware power/oc setup */
 #define        OHCI_QUIRK_AMD_PLL      0x200                   /* AMD PLL quirk*/
 #define        OHCI_QUIRK_AMD_PREFETCH 0x400                   /* pre-fetch for ISO transfer */
-#define        OHCI_QUIRK_SHUTDOWN     0x800                   /* nVidia power bug */
        // there are also chip quirks/bugs in init logic
 
        struct work_struct      nec_work;       /* Worker for NEC quirk */
index 27a3dec..caf8742 100644 (file)
@@ -37,6 +37,7 @@
 #define OHCI_INTRENABLE                0x10
 #define OHCI_INTRDISABLE       0x14
 #define OHCI_FMINTERVAL                0x34
+#define OHCI_HCFS              (3 << 6)        /* hc functional state */
 #define OHCI_HCR               (1 << 0)        /* host controller reset */
 #define OHCI_OCR               (1 << 3)        /* ownership change request */
 #define OHCI_CTRL_RWC          (1 << 9)        /* remote wakeup connected */
@@ -466,6 +467,8 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
 {
        void __iomem *base;
        u32 control;
+       u32 fminterval;
+       int cnt;
 
        if (!mmio_resource_enabled(pdev, 0))
                return;
@@ -498,41 +501,32 @@ static void __devinit quirk_usb_handoff_ohci(struct pci_dev *pdev)
        }
 #endif
 
-       /* reset controller, preserving RWC (and possibly IR) */
-       writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
-       readl(base + OHCI_CONTROL);
+       /* disable interrupts */
+       writel((u32) ~0, base + OHCI_INTRDISABLE);
 
-       /* Some NVIDIA controllers stop working if kept in RESET for too long */
-       if (pdev->vendor == PCI_VENDOR_ID_NVIDIA) {
-               u32 fminterval;
-               int cnt;
+       /* Reset the USB bus, if the controller isn't already in RESET */
+       if (control & OHCI_HCFS) {
+               /* Go into RESET, preserving RWC (and possibly IR) */
+               writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL);
+               readl(base + OHCI_CONTROL);
 
-               /* drive reset for at least 50 ms (7.1.7.5) */
+               /* drive bus reset for at least 50 ms (7.1.7.5) */
                msleep(50);
+       }
 
-               /* software reset of the controller, preserving HcFmInterval */
-               fminterval = readl(base + OHCI_FMINTERVAL);
-               writel(OHCI_HCR, base + OHCI_CMDSTATUS);
+       /* software reset of the controller, preserving HcFmInterval */
+       fminterval = readl(base + OHCI_FMINTERVAL);
+       writel(OHCI_HCR, base + OHCI_CMDSTATUS);
 
-               /* reset requires max 10 us delay */
-               for (cnt = 30; cnt > 0; --cnt) {        /* ... allow extra time */
-                       if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
-                               break;
-                       udelay(1);
-               }
-               writel(fminterval, base + OHCI_FMINTERVAL);
-
-               /* Now we're in the SUSPEND state with all devices reset
-                * and wakeups and interrupts disabled
-                */
+       /* reset requires max 10 us delay */
+       for (cnt = 30; cnt > 0; --cnt) {        /* ... allow extra time */
+               if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0)
+                       break;
+               udelay(1);
        }
+       writel(fminterval, base + OHCI_FMINTERVAL);
 
-       /*
-        * disable interrupts
-        */
-       writel(~(u32)0, base + OHCI_INTRDISABLE);
-       writel(~(u32)0, base + OHCI_INTRSTATUS);
-
+       /* Now the controller is safely in SUSPEND and nothing can wake it up */
        iounmap(base);
 }
 
@@ -627,7 +621,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
        void __iomem *base, *op_reg_base;
        u32     hcc_params, cap, val;
        u8      offset, cap_length;
-       int     wait_time, delta, count = 256/4;
+       int     wait_time, count = 256/4;
 
        if (!mmio_resource_enabled(pdev, 0))
                return;
@@ -673,11 +667,10 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev)
                writel(val, op_reg_base + EHCI_USBCMD);
 
                wait_time = 2000;
-               delta = 100;
                do {
                        writel(0x3f, op_reg_base + EHCI_USBSTS);
-                       udelay(delta);
-                       wait_time -= delta;
+                       udelay(100);
+                       wait_time -= 100;
                        val = readl(op_reg_base + EHCI_USBSTS);
                        if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) {
                                break;
index 42a22b8..0e4b25f 100644 (file)
@@ -982,7 +982,6 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
        struct xhci_virt_device *dev;
        struct xhci_ep_ctx      *ep0_ctx;
        struct xhci_slot_ctx    *slot_ctx;
-       struct xhci_input_control_ctx *ctrl_ctx;
        u32                     port_num;
        struct usb_device *top_dev;
 
@@ -994,12 +993,8 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
                return -EINVAL;
        }
        ep0_ctx = xhci_get_ep_ctx(xhci, dev->in_ctx, 0);
-       ctrl_ctx = xhci_get_input_control_ctx(xhci, dev->in_ctx);
        slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
 
-       /* 2) New slot context and endpoint 0 context are valid*/
-       ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
-
        /* 3) Only the control endpoint is valid - one endpoint context */
        slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | udev->route);
        switch (udev->speed) {
index 940321b..9f1d4b1 100644 (file)
@@ -816,23 +816,24 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
        struct xhci_ring *ring;
        struct xhci_td *cur_td;
        int ret, i, j;
+       unsigned long flags;
 
        ep = (struct xhci_virt_ep *) arg;
        xhci = ep->xhci;
 
-       spin_lock(&xhci->lock);
+       spin_lock_irqsave(&xhci->lock, flags);
 
        ep->stop_cmds_pending--;
        if (xhci->xhc_state & XHCI_STATE_DYING) {
                xhci_dbg(xhci, "Stop EP timer ran, but another timer marked "
                                "xHCI as DYING, exiting.\n");
-               spin_unlock(&xhci->lock);
+               spin_unlock_irqrestore(&xhci->lock, flags);
                return;
        }
        if (!(ep->stop_cmds_pending == 0 && (ep->ep_state & EP_HALT_PENDING))) {
                xhci_dbg(xhci, "Stop EP timer ran, but no command pending, "
                                "exiting.\n");
-               spin_unlock(&xhci->lock);
+               spin_unlock_irqrestore(&xhci->lock, flags);
                return;
        }
 
@@ -844,11 +845,11 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
        xhci->xhc_state |= XHCI_STATE_DYING;
        /* Disable interrupts from the host controller and start halting it */
        xhci_quiesce(xhci);
-       spin_unlock(&xhci->lock);
+       spin_unlock_irqrestore(&xhci->lock, flags);
 
        ret = xhci_halt(xhci);
 
-       spin_lock(&xhci->lock);
+       spin_lock_irqsave(&xhci->lock, flags);
        if (ret < 0) {
                /* This is bad; the host is not responding to commands and it's
                 * not allowing itself to be halted.  At least interrupts are
@@ -896,7 +897,7 @@ void xhci_stop_endpoint_command_watchdog(unsigned long arg)
                        }
                }
        }
-       spin_unlock(&xhci->lock);
+       spin_unlock_irqrestore(&xhci->lock, flags);
        xhci_dbg(xhci, "Calling usb_hc_died()\n");
        usb_hc_died(xhci_to_hcd(xhci)->primary_hcd);
        xhci_dbg(xhci, "xHCI host controller is dead.\n");
index 1ff95a0..aa94c01 100644 (file)
@@ -799,7 +799,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
        u32                     command, temp = 0;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        struct usb_hcd          *secondary_hcd;
-       int                     retval;
+       int                     retval = 0;
 
        /* Wait a bit if either of the roothubs need to settle from the
         * transition into bus suspend.
@@ -809,6 +809,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                                xhci->bus_state[1].next_statechange))
                msleep(100);
 
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+       set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
+
        spin_lock_irq(&xhci->lock);
        if (xhci->quirks & XHCI_RESET_ON_RESUME)
                hibernated = true;
@@ -878,20 +881,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                        return retval;
                xhci_dbg(xhci, "Start the primary HCD\n");
                retval = xhci_run(hcd->primary_hcd);
-               if (retval)
-                       goto failed_restart;
-
-               xhci_dbg(xhci, "Start the secondary HCD\n");
-               retval = xhci_run(secondary_hcd);
                if (!retval) {
-                       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-                       set_bit(HCD_FLAG_HW_ACCESSIBLE,
-                                       &xhci->shared_hcd->flags);
+                       xhci_dbg(xhci, "Start the secondary HCD\n");
+                       retval = xhci_run(secondary_hcd);
                }
-failed_restart:
                hcd->state = HC_STATE_SUSPENDED;
                xhci->shared_hcd->state = HC_STATE_SUSPENDED;
-               return retval;
+               goto done;
        }
 
        /* step 4: set Run/Stop bit */
@@ -910,11 +906,14 @@ failed_restart:
         * Running endpoints by ringing their doorbells
         */
 
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-       set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
-
        spin_unlock_irq(&xhci->lock);
-       return 0;
+
+ done:
+       if (retval == 0) {
+               usb_hcd_resume_root_hub(hcd);
+               usb_hcd_resume_root_hub(xhci->shared_hcd);
+       }
+       return retval;
 }
 #endif /* CONFIG_PM */
 
@@ -3504,6 +3503,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
        /* Otherwise, update the control endpoint ring enqueue pointer. */
        else
                xhci_copy_ep0_dequeue_into_input_ctx(xhci, udev);
+       ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
+       ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
+       ctrl_ctx->drop_flags = 0;
+
        xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
        xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2);
 
@@ -3585,7 +3588,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
        virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
                + 1;
        /* Zero the input context control for later use */
-       ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
        ctrl_ctx->add_flags = 0;
        ctrl_ctx->drop_flags = 0;
 
index fc34b8b..07a0346 100644 (file)
@@ -11,6 +11,7 @@ config USB_MUSB_HDRC
        select TWL4030_USB if MACH_OMAP_3430SDP
        select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
        select USB_OTG_UTILS
+       select USB_GADGET_DUALSPEED
        tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
        help
          Say Y here if your system has a dual role high speed USB
@@ -60,7 +61,7 @@ config USB_MUSB_BLACKFIN
 
 config USB_MUSB_UX500
        tristate "U8500 and U5500"
-       depends on (ARCH_U8500 && AB8500_USB) || (ARCH_U5500)
+       depends on (ARCH_U8500 && AB8500_USB)
 
 endchoice
 
index 08f1d0b..e233d2b 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
index 4da7492..2613bfd 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
index 20a2873..c1fa12e 100644 (file)
@@ -1477,8 +1477,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb)
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430) || \
-       defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500) || \
-       defined(CONFIG_ARCH_U5500)
+       defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_U8500)
 
 static irqreturn_t generic_interrupt(int irq, void *__hci)
 {
index ae4a20a..d51043a 100644 (file)
@@ -1999,10 +1999,6 @@ static void stop_activity(struct musb *musb, struct usb_gadget_driver *driver)
                                        nuke(&hw_ep->ep_out, -ESHUTDOWN);
                        }
                }
-
-               spin_unlock(&musb->lock);
-               driver->disconnect(&musb->g);
-               spin_lock(&musb->lock);
        }
 }
 
index d2e2efa..08c679c 100644 (file)
@@ -405,7 +405,7 @@ int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
 /*
  *             platform functions
  */
-static int __devinit usbhs_probe(struct platform_device *pdev)
+static int usbhs_probe(struct platform_device *pdev)
 {
        struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
        struct renesas_usbhs_driver_callback *dfunc;
index 8da685e..ffdf5d1 100644 (file)
@@ -820,7 +820,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
        if (len % 4) /* 32bit alignment */
                goto usbhsf_pio_prepare_push;
 
-       if ((*(u32 *) pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
+       if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_push;
 
        /* get enable DMA fifo */
@@ -897,7 +897,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
        if (!fifo)
                goto usbhsf_pio_prepare_pop;
 
-       if ((*(u32 *) pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
+       if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_pop;
 
        ret = usbhsf_fifo_select(pipe, fifo, 0);
index 8ae3733..6c68755 100644 (file)
@@ -143,8 +143,8 @@ void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod);
  */
 #if    defined(CONFIG_USB_RENESAS_USBHS_HCD) || \
        defined(CONFIG_USB_RENESAS_USBHS_HCD_MODULE)
-extern int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv);
-extern int __devexit usbhs_mod_host_remove(struct usbhs_priv *priv);
+extern int usbhs_mod_host_probe(struct usbhs_priv *priv);
+extern int usbhs_mod_host_remove(struct usbhs_priv *priv);
 #else
 static inline int usbhs_mod_host_probe(struct usbhs_priv *priv)
 {
@@ -157,8 +157,8 @@ static inline void usbhs_mod_host_remove(struct usbhs_priv *priv)
 
 #if    defined(CONFIG_USB_RENESAS_USBHS_UDC) || \
        defined(CONFIG_USB_RENESAS_USBHS_UDC_MODULE)
-extern int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv);
-extern void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv);
+extern int usbhs_mod_gadget_probe(struct usbhs_priv *priv);
+extern void usbhs_mod_gadget_remove(struct usbhs_priv *priv);
 #else
 static inline int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
index 4cc7ee0..d9717e0 100644 (file)
@@ -830,7 +830,7 @@ static int usbhsg_stop(struct usbhs_priv *priv)
        return usbhsg_try_stop(priv, USBHSG_STATUS_STARTED);
 }
 
-int __devinit usbhs_mod_gadget_probe(struct usbhs_priv *priv)
+int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
 {
        struct usbhsg_gpriv *gpriv;
        struct usbhsg_uep *uep;
@@ -927,7 +927,7 @@ usbhs_mod_gadget_probe_err_gpriv:
        return ret;
 }
 
-void __devexit usbhs_mod_gadget_remove(struct usbhs_priv *priv)
+void usbhs_mod_gadget_remove(struct usbhs_priv *priv)
 {
        struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
 
index 1a7208a..bade761 100644 (file)
@@ -103,7 +103,7 @@ struct usbhsh_hpriv {
 
        u32     port_stat;      /* USB_PORT_STAT_xxx */
 
-       struct completion       *done;
+       struct completion       setup_ack_done;
 
        /* see usbhsh_req_alloc/free */
        struct list_head        ureq_link_active;
@@ -355,6 +355,7 @@ static void usbhsh_device_free(struct usbhsh_hpriv *hpriv,
 struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
                                        struct usbhsh_device *udev,
                                        struct usb_host_endpoint *ep,
+                                       int dir_in_req,
                                        gfp_t mem_flags)
 {
        struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
@@ -364,27 +365,38 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
        struct usbhs_pipe *pipe, *best_pipe;
        struct device *dev = usbhsh_hcd_to_dev(hcd);
        struct usb_endpoint_descriptor *desc = &ep->desc;
-       int type, i;
+       int type, i, dir_in;
        unsigned int min_usr;
 
+       dir_in_req = !!dir_in_req;
+
        uep = kzalloc(sizeof(struct usbhsh_ep), mem_flags);
        if (!uep) {
                dev_err(dev, "usbhsh_ep alloc fail\n");
                return NULL;
        }
-       type = usb_endpoint_type(desc);
+
+       if (usb_endpoint_xfer_control(desc)) {
+               best_pipe = usbhsh_hpriv_to_dcp(hpriv);
+               goto usbhsh_endpoint_alloc_find_pipe;
+       }
 
        /*
         * find best pipe for endpoint
         * see
         *      HARDWARE LIMITATION
         */
+       type = usb_endpoint_type(desc);
        min_usr = ~0;
        best_pipe = NULL;
-       usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
+       usbhs_for_each_pipe(pipe, priv, i) {
                if (!usbhs_pipe_type_is(pipe, type))
                        continue;
 
+               dir_in = !!usbhs_pipe_is_dir_in(pipe);
+               if (0 != (dir_in - dir_in_req))
+                       continue;
+
                info = usbhsh_pipe_info(pipe);
 
                if (min_usr > info->usr_cnt) {
@@ -398,7 +410,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
                kfree(uep);
                return NULL;
        }
-
+usbhsh_endpoint_alloc_find_pipe:
        /*
         * init uep
         */
@@ -423,6 +435,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
         * see
         *  DCPMAXP/PIPEMAXP
         */
+       usbhs_pipe_sequence_data0(uep->pipe);
        usbhs_pipe_config_update(uep->pipe,
                                 usbhsh_device_number(hpriv, udev),
                                 usb_endpoint_num(desc),
@@ -430,7 +443,7 @@ struct usbhsh_ep *usbhsh_endpoint_alloc(struct usbhsh_hpriv *hpriv,
 
        dev_dbg(dev, "%s [%d-%s](%p)\n", __func__,
                usbhsh_device_number(hpriv, udev),
-               usbhs_pipe_name(pipe), uep);
+               usbhs_pipe_name(uep->pipe), uep);
 
        return uep;
 }
@@ -549,8 +562,7 @@ static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv,
         *      usbhsh_irq_setup_ack()
         *      usbhsh_irq_setup_err()
         */
-       DECLARE_COMPLETION(done);
-       hpriv->done = &done;
+       init_completion(&hpriv->setup_ack_done);
 
        /* copy original request */
        memcpy(&req, urb->setup_packet, sizeof(struct usb_ctrlrequest));
@@ -572,8 +584,7 @@ static void usbhsh_setup_stage_packet_push(struct usbhsh_hpriv *hpriv,
        /*
         * wait setup packet ACK
         */
-       wait_for_completion(&done);
-       hpriv->done = NULL;
+       wait_for_completion(&hpriv->setup_ack_done);
 
        dev_dbg(dev, "%s done\n", __func__);
 }
@@ -724,11 +735,11 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
        struct usbhsh_device *udev, *new_udev = NULL;
        struct usbhs_pipe *pipe;
        struct usbhsh_ep *uep;
+       int is_dir_in = usb_pipein(urb->pipe);
 
        int ret;
 
-       dev_dbg(dev, "%s (%s)\n",
-               __func__, usb_pipein(urb->pipe) ? "in" : "out");
+       dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out");
 
        ret = usb_hcd_link_urb_to_ep(hcd, urb);
        if (ret)
@@ -751,7 +762,8 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
         */
        uep = usbhsh_ep_to_uep(ep);
        if (!uep) {
-               uep = usbhsh_endpoint_alloc(hpriv, udev, ep, mem_flags);
+               uep = usbhsh_endpoint_alloc(hpriv, udev, ep,
+                                           is_dir_in, mem_flags);
                if (!uep)
                        goto usbhsh_urb_enqueue_error_free_device;
        }
@@ -1095,10 +1107,7 @@ static int usbhsh_irq_setup_ack(struct usbhs_priv *priv,
 
        dev_dbg(dev, "setup packet OK\n");
 
-       if (unlikely(!hpriv->done))
-               dev_err(dev, "setup ack happen without necessary data\n");
-       else
-               complete(hpriv->done); /* see usbhsh_urb_enqueue() */
+       complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */
 
        return 0;
 }
@@ -1111,10 +1120,7 @@ static int usbhsh_irq_setup_err(struct usbhs_priv *priv,
 
        dev_dbg(dev, "setup packet Err\n");
 
-       if (unlikely(!hpriv->done))
-               dev_err(dev, "setup err happen without necessary data\n");
-       else
-               complete(hpriv->done); /* see usbhsh_urb_enqueue() */
+       complete(&hpriv->setup_ack_done); /* see usbhsh_urb_enqueue() */
 
        return 0;
 }
@@ -1221,8 +1227,18 @@ static int usbhsh_stop(struct usbhs_priv *priv)
 {
        struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv);
        struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv);
+       struct usbhs_mod *mod = usbhs_mod_get_current(priv);
        struct device *dev = usbhs_priv_to_dev(priv);
 
+       /*
+        * disable irq callback
+        */
+       mod->irq_attch  = NULL;
+       mod->irq_dtch   = NULL;
+       mod->irq_sack   = NULL;
+       mod->irq_sign   = NULL;
+       usbhs_irq_callback_update(priv, mod);
+
        usb_remove_hcd(hcd);
 
        /* disable sys */
@@ -1235,7 +1251,7 @@ static int usbhsh_stop(struct usbhs_priv *priv)
        return 0;
 }
 
-int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv)
+int usbhs_mod_host_probe(struct usbhs_priv *priv)
 {
        struct usbhsh_hpriv *hpriv;
        struct usb_hcd *hcd;
@@ -1279,7 +1295,6 @@ int __devinit usbhs_mod_host_probe(struct usbhs_priv *priv)
        hpriv->mod.stop         = usbhsh_stop;
        hpriv->pipe_info        = pipe_info;
        hpriv->pipe_size        = pipe_size;
-       hpriv->done             = NULL;
        usbhsh_req_list_init(hpriv);
        usbhsh_port_stat_init(hpriv);
 
@@ -1299,7 +1314,7 @@ usbhs_mod_host_probe_err:
        return -ENOMEM;
 }
 
-int __devexit usbhs_mod_host_remove(struct usbhs_priv *priv)
+int usbhs_mod_host_remove(struct usbhs_priv *priv)
 {
        struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv);
        struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv);
index 5cdb9d9..18e875b 100644 (file)
@@ -42,7 +42,7 @@ static int debug;
  * Version information
  */
 
-#define DRIVER_VERSION "v0.6"
+#define DRIVER_VERSION "v0.7"
 #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"
 #define DRIVER_DESC "USB ARK3116 serial/IrDA driver"
 #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA"
@@ -380,10 +380,6 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
                goto err_out;
        }
 
-       /* setup termios */
-       if (tty)
-               ark3116_set_termios(tty, port, NULL);
-
        /* remove any data still left: also clears error state */
        ark3116_read_reg(serial, UART_RX, buf);
 
@@ -406,6 +402,10 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
        /* enable DMA */
        ark3116_write_reg(port->serial, UART_FCR, UART_FCR_DMA_SELECT);
 
+       /* setup termios */
+       if (tty)
+               ark3116_set_termios(tty, port, NULL);
+
 err_out:
        kfree(buf);
        return result;
index 8fe034d..bd4298b 100644 (file)
@@ -2104,13 +2104,19 @@ static void ftdi_set_termios(struct tty_struct *tty,
 
        cflag = termios->c_cflag;
 
-       /* FIXME -For this cut I don't care if the line is really changing or
-          not  - so just do the change regardless  - should be able to
-          compare old_termios and tty->termios */
+       if (old_termios->c_cflag == termios->c_cflag
+           && old_termios->c_ispeed == termios->c_ispeed
+           && old_termios->c_ospeed == termios->c_ospeed)
+               goto no_c_cflag_changes;
+
        /* NOTE These routines can get interrupted by
           ftdi_sio_read_bulk_callback  - need to examine what this means -
           don't see any problems yet */
 
+       if ((old_termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)) ==
+           (termios->c_cflag & (CSIZE|PARODD|PARENB|CMSPAR|CSTOPB)))
+               goto no_data_parity_stop_changes;
+
        /* Set number of data bits, parity, stop bits */
 
        urb_value = 0;
@@ -2151,6 +2157,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
        }
 
        /* Now do the baudrate */
+no_data_parity_stop_changes:
        if ((cflag & CBAUD) == B0) {
                /* Disable flow control */
                if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
@@ -2178,6 +2185,7 @@ static void ftdi_set_termios(struct tty_struct *tty,
 
        /* Set flow control */
        /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */
+no_c_cflag_changes:
        if (cflag & CRTSCTS) {
                dbg("%s Setting to CRTSCTS flow control", __func__);
                if (usb_control_msg(dev,
index 89ae1f6..d865878 100644 (file)
@@ -156,6 +156,7 @@ static void option_instat_callback(struct urb *urb);
 #define HUAWEI_PRODUCT_K4511                   0x14CC
 #define HUAWEI_PRODUCT_ETS1220                 0x1803
 #define HUAWEI_PRODUCT_E353                    0x1506
+#define HUAWEI_PRODUCT_E173S                   0x1C05
 
 #define QUANTA_VENDOR_ID                       0x0408
 #define QUANTA_PRODUCT_Q101                    0xEA02
@@ -316,6 +317,9 @@ static void option_instat_callback(struct urb *urb);
 #define ZTE_PRODUCT_AC8710                     0xfff1
 #define ZTE_PRODUCT_AC2726                     0xfff5
 #define ZTE_PRODUCT_AC8710T                    0xffff
+#define ZTE_PRODUCT_MC2718                     0xffe8
+#define ZTE_PRODUCT_AD3812                     0xffeb
+#define ZTE_PRODUCT_MC2716                     0xffed
 
 #define BENQ_VENDOR_ID                         0x04a5
 #define BENQ_PRODUCT_H10                       0x4068
@@ -468,6 +472,10 @@ static void option_instat_callback(struct urb *urb);
 #define YUGA_PRODUCT_CLU528                    0x260D
 #define YUGA_PRODUCT_CLU526                    0x260F
 
+/* Viettel products */
+#define VIETTEL_VENDOR_ID                      0x2262
+#define VIETTEL_PRODUCT_VT1000                 0x0002
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -500,6 +508,18 @@ static const struct option_blacklist_info zte_k3765_z_blacklist = {
        .reserved = BIT(4),
 };
 
+static const struct option_blacklist_info zte_ad3812_z_blacklist = {
+       .sendsetup = BIT(0) | BIT(1) | BIT(2),
+};
+
+static const struct option_blacklist_info zte_mc2718_z_blacklist = {
+       .sendsetup = BIT(1) | BIT(2) | BIT(3) | BIT(4),
+};
+
+static const struct option_blacklist_info zte_mc2716_z_blacklist = {
+       .sendsetup = BIT(1) | BIT(2) | BIT(3),
+};
+
 static const struct option_blacklist_info huawei_cdc12_blacklist = {
        .reserved = BIT(1) | BIT(2),
 };
@@ -622,6 +642,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff),
@@ -1043,6 +1064,12 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2718, 0xff, 0xff, 0xff),
+        .driver_info = (kernel_ulong_t)&zte_mc2718_z_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AD3812, 0xff, 0xff, 0xff),
+        .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
+       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
+        .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
        { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
@@ -1141,6 +1168,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) },
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) },
        { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) },
+       { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) },
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 9083d1e..fc2d66f 100644 (file)
@@ -91,7 +91,6 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
        { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
        { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
-       { USB_DEVICE(WINCHIPHEAD_VENDOR_ID, WINCHIPHEAD_USBSER_PRODUCT_ID) },
        { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },
        { }                                     /* Terminating entry */
 };
index 3d10d7f..c38b8c0 100644 (file)
 #define ADLINK_VENDOR_ID               0x0b63
 #define ADLINK_ND6530_PRODUCT_ID       0x6530
 
-/* WinChipHead USB->RS 232 adapter */
-#define WINCHIPHEAD_VENDOR_ID          0x4348
-#define WINCHIPHEAD_USBSER_PRODUCT_ID  0x5523
-
 /* SMART USB Serial Adapter */
 #define SMART_VENDOR_ID        0x0b8c
 #define SMART_PRODUCT_ID       0x2303
index 4dca3ef..9fbe742 100644 (file)
@@ -1762,10 +1762,9 @@ static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
                result = ene_send_scsi_cmd(us, FDIR_WRITE, scsi_sglist(srb), 1);
        } else {
                void *buf;
-               int offset;
+               int offset = 0;
                u16 PhyBlockAddr;
                u8 PageNum;
-               u32 result;
                u16 len, oldphy, newphy;
 
                buf = kmalloc(blenByte, GFP_KERNEL);
index 93c1a4d..82dd834 100644 (file)
@@ -59,7 +59,9 @@
 
 void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
 {
-       /* Pad the SCSI command with zeros out to 12 bytes
+       /*
+        * Pad the SCSI command with zeros out to 12 bytes.  If the
+        * command already is 12 bytes or longer, leave it alone.
         *
         * NOTE: This only works because a scsi_cmnd struct field contains
         * a unsigned char cmnd[16], so we know we have storage available
@@ -67,9 +69,6 @@ void usb_stor_pad12_command(struct scsi_cmnd *srb, struct us_data *us)
        for (; srb->cmd_len<12; srb->cmd_len++)
                srb->cmnd[srb->cmd_len] = 0;
 
-       /* set command length to 12 bytes */
-       srb->cmd_len = 12;
-
        /* send the command to the transport layer */
        usb_stor_invoke_transport(srb, us);
 }
index 55f91d9..29577bf 100644 (file)
 /* Clock registers available only on Version 2 */
 #define  LCD_CLK_ENABLE_REG                    0x6c
 #define  LCD_CLK_RESET_REG                     0x70
+#define  LCD_CLK_MAIN_RESET                    BIT(3)
 
 #define LCD_NUM_BUFFERS        2
 
@@ -244,6 +245,10 @@ static inline void lcd_enable_raster(void)
 {
        u32 reg;
 
+       /* Bring LCDC out of reset */
+       if (lcd_revision == LCD_VERSION_2)
+               lcdc_write(0, LCD_CLK_RESET_REG);
+
        reg = lcdc_read(LCD_RASTER_CTRL_REG);
        if (!(reg & LCD_RASTER_ENABLE))
                lcdc_write(reg | LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
@@ -257,6 +262,10 @@ static inline void lcd_disable_raster(void)
        reg = lcdc_read(LCD_RASTER_CTRL_REG);
        if (reg & LCD_RASTER_ENABLE)
                lcdc_write(reg & ~LCD_RASTER_ENABLE, LCD_RASTER_CTRL_REG);
+
+       if (lcd_revision == LCD_VERSION_2)
+               /* Write 1 to reset LCDC */
+               lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
 }
 
 static void lcd_blit(int load_mode, struct da8xx_fb_par *par)
@@ -584,8 +593,12 @@ static void lcd_reset(struct da8xx_fb_par *par)
        lcdc_write(0, LCD_DMA_CTRL_REG);
        lcdc_write(0, LCD_RASTER_CTRL_REG);
 
-       if (lcd_revision == LCD_VERSION_2)
+       if (lcd_revision == LCD_VERSION_2) {
                lcdc_write(0, LCD_INT_ENABLE_SET_REG);
+               /* Write 1 to reset */
+               lcdc_write(LCD_CLK_MAIN_RESET, LCD_CLK_RESET_REG);
+               lcdc_write(0, LCD_CLK_RESET_REG);
+       }
 }
 
 static void lcd_calc_clk_divider(struct da8xx_fb_par *par)
index 0ccd7ad..6f61e78 100644 (file)
@@ -19,6 +19,7 @@
  * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
index 3532782..5c81533 100644 (file)
@@ -1720,12 +1720,11 @@ static int dispc_ovl_calc_scaling(enum omap_plane plane,
        const int maxdownscale = dss_feat_get_param_max(FEAT_PARAM_DOWNSCALE);
        unsigned long fclk = 0;
 
-       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0) {
-               if (width != out_width || height != out_height)
-                       return -EINVAL;
-               else
-                       return 0;
-       }
+       if (width == out_width && height == out_height)
+               return 0;
+
+       if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0)
+               return -EINVAL;
 
        if (out_width < width / maxdownscale ||
                        out_width > width * 8)
index 3262f0f..c56378c 100644 (file)
@@ -269,7 +269,7 @@ static void update_hdmi_timings(struct hdmi_config *cfg,
 unsigned long hdmi_get_pixel_clock(void)
 {
        /* HDMI Pixel Clock in Mhz */
-       return hdmi.ip_data.cfg.timings.timings.pixel_clock * 10000;
+       return hdmi.ip_data.cfg.timings.timings.pixel_clock * 1000;
 }
 
 static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy,
index 69d882c..c01c1c1 100644 (file)
 #define M1200X720_R60_VSP       POSITIVE
 
 /* 1200x900@60 Sync Polarity (DCON) */
-#define M1200X900_R60_HSP       NEGATIVE
-#define M1200X900_R60_VSP       NEGATIVE
+#define M1200X900_R60_HSP       POSITIVE
+#define M1200X900_R60_VSP       POSITIVE
 
 /* 1280x600@60 Sync Polarity (GTF Mode) */
 #define M1280x600_R60_HSP       NEGATIVE
index 816ed08..1a61939 100644 (file)
@@ -37,7 +37,7 @@ config VIRTIO_BALLOON
 
  config VIRTIO_MMIO
        tristate "Platform bus driver for memory mapped virtio devices (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on HAS_IOMEM && EXPERIMENTAL
        select VIRTIO
        select VIRTIO_RING
        ---help---
index acc5e43..7317dc2 100644 (file)
@@ -118,7 +118,7 @@ static void vm_finalize_features(struct virtio_device *vdev)
        vring_transport_features(vdev);
 
        for (i = 0; i < ARRAY_SIZE(vdev->features); i++) {
-               writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SET);
+               writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SEL);
                writel(vdev->features[i],
                                vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES);
        }
index 79a31e5..03d1984 100644 (file)
@@ -169,11 +169,29 @@ static void vp_set_status(struct virtio_device *vdev, u8 status)
        iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
 }
 
+/* wait for pending irq handlers */
+static void vp_synchronize_vectors(struct virtio_device *vdev)
+{
+       struct virtio_pci_device *vp_dev = to_vp_device(vdev);
+       int i;
+
+       if (vp_dev->intx_enabled)
+               synchronize_irq(vp_dev->pci_dev->irq);
+
+       for (i = 0; i < vp_dev->msix_vectors; ++i)
+               synchronize_irq(vp_dev->msix_entries[i].vector);
+}
+
 static void vp_reset(struct virtio_device *vdev)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        /* 0 status means a reset. */
        iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+       /* Flush out the status write, and flush in device writes,
+        * including MSi-X interrupts, if any. */
+       ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS);
+       /* Flush pending VQ/configuration callbacks. */
+       vp_synchronize_vectors(vdev);
 }
 
 /* the notify function used when creating a virt queue */
@@ -594,11 +612,11 @@ static struct virtio_config_ops virtio_pci_config_ops = {
 
 static void virtio_pci_release_dev(struct device *_d)
 {
-       struct virtio_device *dev = container_of(_d, struct virtio_device,
-                                                dev);
-       struct virtio_pci_device *vp_dev = to_vp_device(dev);
-
-       kfree(vp_dev);
+       /*
+        * No need for a release method as we allocate/free
+        * all devices together with the pci devices.
+        * Provide an empty one to avoid getting a warning from core.
+        */
 }
 
 /* the PCI probing function */
@@ -686,6 +704,7 @@ static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
        pci_iounmap(pci_dev, vp_dev->ioaddr);
        pci_release_regions(pci_dev);
        pci_disable_device(pci_dev);
+       kfree(vp_dev);
 }
 
 #ifdef CONFIG_PM
index 6285867..79fd606 100644 (file)
@@ -314,13 +314,6 @@ config NUC900_WATCHDOG
          To compile this driver as a module, choose M here: the
          module will be called nuc900_wdt.
 
-config ADX_WATCHDOG
-       tristate "Avionic Design Xanthos watchdog"
-       depends on ARCH_PXA_ADX
-       help
-         Say Y here if you want support for the watchdog timer on Avionic
-         Design Xanthos boards.
-
 config TS72XX_WATCHDOG
        tristate "TS-72XX SBC Watchdog"
        depends on MACH_TS72XX
index 55bd574..fe893e9 100644 (file)
@@ -51,7 +51,6 @@ obj-$(CONFIG_ORION_WATCHDOG) += orion_wdt.o
 obj-$(CONFIG_COH901327_WATCHDOG) += coh901327_wdt.o
 obj-$(CONFIG_STMP3XXX_WATCHDOG) += stmp3xxx_wdt.o
 obj-$(CONFIG_NUC900_WATCHDOG) += nuc900_wdt.o
-obj-$(CONFIG_ADX_WATCHDOG) += adx_wdt.o
 obj-$(CONFIG_TS72XX_WATCHDOG) += ts72xx_wdt.o
 obj-$(CONFIG_IMX2_WDT) += imx2_wdt.o
 
diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c
deleted file mode 100644 (file)
index af6e6b1..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Avionic Design GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/fs.h>
-#include <linux/gfp.h>
-#include <linux/io.h>
-#include <linux/miscdevice.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-#include <linux/uaccess.h>
-#include <linux/watchdog.h>
-
-#define WATCHDOG_NAME "adx-wdt"
-
-/* register offsets */
-#define        ADX_WDT_CONTROL         0x00
-#define        ADX_WDT_CONTROL_ENABLE  (1 << 0)
-#define        ADX_WDT_CONTROL_nRESET  (1 << 1)
-#define        ADX_WDT_TIMEOUT         0x08
-
-static struct platform_device *adx_wdt_dev;
-static unsigned long driver_open;
-
-#define        WDT_STATE_STOP  0
-#define        WDT_STATE_START 1
-
-struct adx_wdt {
-       void __iomem *base;
-       unsigned long timeout;
-       unsigned int state;
-       unsigned int wake;
-       spinlock_t lock;
-};
-
-static const struct watchdog_info adx_wdt_info = {
-       .identity = "Avionic Design Xanthos Watchdog",
-       .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-};
-
-static void adx_wdt_start_locked(struct adx_wdt *wdt)
-{
-       u32 ctrl;
-
-       ctrl = readl(wdt->base + ADX_WDT_CONTROL);
-       ctrl |= ADX_WDT_CONTROL_ENABLE;
-       writel(ctrl, wdt->base + ADX_WDT_CONTROL);
-       wdt->state = WDT_STATE_START;
-}
-
-static void adx_wdt_start(struct adx_wdt *wdt)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&wdt->lock, flags);
-       adx_wdt_start_locked(wdt);
-       spin_unlock_irqrestore(&wdt->lock, flags);
-}
-
-static void adx_wdt_stop_locked(struct adx_wdt *wdt)
-{
-       u32 ctrl;
-
-       ctrl = readl(wdt->base + ADX_WDT_CONTROL);
-       ctrl &= ~ADX_WDT_CONTROL_ENABLE;
-       writel(ctrl, wdt->base + ADX_WDT_CONTROL);
-       wdt->state = WDT_STATE_STOP;
-}
-
-static void adx_wdt_stop(struct adx_wdt *wdt)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&wdt->lock, flags);
-       adx_wdt_stop_locked(wdt);
-       spin_unlock_irqrestore(&wdt->lock, flags);
-}
-
-static void adx_wdt_set_timeout(struct adx_wdt *wdt, unsigned long seconds)
-{
-       unsigned long timeout = seconds * 1000;
-       unsigned long flags;
-       unsigned int state;
-
-       spin_lock_irqsave(&wdt->lock, flags);
-       state = wdt->state;
-       adx_wdt_stop_locked(wdt);
-       writel(timeout, wdt->base + ADX_WDT_TIMEOUT);
-
-       if (state == WDT_STATE_START)
-               adx_wdt_start_locked(wdt);
-
-       wdt->timeout = timeout;
-       spin_unlock_irqrestore(&wdt->lock, flags);
-}
-
-static void adx_wdt_get_timeout(struct adx_wdt *wdt, unsigned long *seconds)
-{
-       *seconds = wdt->timeout / 1000;
-}
-
-static void adx_wdt_keepalive(struct adx_wdt *wdt)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&wdt->lock, flags);
-       writel(wdt->timeout, wdt->base + ADX_WDT_TIMEOUT);
-       spin_unlock_irqrestore(&wdt->lock, flags);
-}
-
-static int adx_wdt_open(struct inode *inode, struct file *file)
-{
-       struct adx_wdt *wdt = platform_get_drvdata(adx_wdt_dev);
-
-       if (test_and_set_bit(0, &driver_open))
-               return -EBUSY;
-
-       file->private_data = wdt;
-       adx_wdt_set_timeout(wdt, 30);
-       adx_wdt_start(wdt);
-
-       return nonseekable_open(inode, file);
-}
-
-static int adx_wdt_release(struct inode *inode, struct file *file)
-{
-       struct adx_wdt *wdt = file->private_data;
-
-       adx_wdt_stop(wdt);
-       clear_bit(0, &driver_open);
-
-       return 0;
-}
-
-static long adx_wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       struct adx_wdt *wdt = file->private_data;
-       void __user *argp = (void __user *)arg;
-       unsigned long __user *p = argp;
-       unsigned long seconds = 0;
-       unsigned int options;
-       long ret = -EINVAL;
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-               if (copy_to_user(argp, &adx_wdt_info, sizeof(adx_wdt_info)))
-                       return -EFAULT;
-               else
-                       return 0;
-
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               return put_user(0, p);
-
-       case WDIOC_KEEPALIVE:
-               adx_wdt_keepalive(wdt);
-               return 0;
-
-       case WDIOC_SETTIMEOUT:
-               if (get_user(seconds, p))
-                       return -EFAULT;
-
-               adx_wdt_set_timeout(wdt, seconds);
-
-               /* fallthrough */
-       case WDIOC_GETTIMEOUT:
-               adx_wdt_get_timeout(wdt, &seconds);
-               return put_user(seconds, p);
-
-       case WDIOC_SETOPTIONS:
-               if (copy_from_user(&options, argp, sizeof(options)))
-                       return -EFAULT;
-
-               if (options & WDIOS_DISABLECARD) {
-                       adx_wdt_stop(wdt);
-                       ret = 0;
-               }
-
-               if (options & WDIOS_ENABLECARD) {
-                       adx_wdt_start(wdt);
-                       ret = 0;
-               }
-
-               return ret;
-
-       default:
-               break;
-       }
-
-       return -ENOTTY;
-}
-
-static ssize_t adx_wdt_write(struct file *file, const char __user *data,
-               size_t len, loff_t *ppos)
-{
-       struct adx_wdt *wdt = file->private_data;
-
-       if (len)
-               adx_wdt_keepalive(wdt);
-
-       return len;
-}
-
-static const struct file_operations adx_wdt_fops = {
-       .owner = THIS_MODULE,
-       .llseek = no_llseek,
-       .open = adx_wdt_open,
-       .release = adx_wdt_release,
-       .unlocked_ioctl = adx_wdt_ioctl,
-       .write = adx_wdt_write,
-};
-
-static struct miscdevice adx_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name = "watchdog",
-       .fops = &adx_wdt_fops,
-};
-
-static int __devinit adx_wdt_probe(struct platform_device *pdev)
-{
-       struct resource *res;
-       struct adx_wdt *wdt;
-       int ret = 0;
-       u32 ctrl;
-
-       wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
-       if (!wdt) {
-               dev_err(&pdev->dev, "cannot allocate WDT structure\n");
-               return -ENOMEM;
-       }
-
-       spin_lock_init(&wdt->lock);
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "cannot obtain I/O memory region\n");
-               return -ENXIO;
-       }
-
-       res = devm_request_mem_region(&pdev->dev, res->start,
-                       resource_size(res), res->name);
-       if (!res) {
-               dev_err(&pdev->dev, "cannot request I/O memory region\n");
-               return -ENXIO;
-       }
-
-       wdt->base = devm_ioremap_nocache(&pdev->dev, res->start,
-                       resource_size(res));
-       if (!wdt->base) {
-               dev_err(&pdev->dev, "cannot remap I/O memory region\n");
-               return -ENXIO;
-       }
-
-       /* disable watchdog and reboot on timeout */
-       ctrl = readl(wdt->base + ADX_WDT_CONTROL);
-       ctrl &= ~ADX_WDT_CONTROL_ENABLE;
-       ctrl &= ~ADX_WDT_CONTROL_nRESET;
-       writel(ctrl, wdt->base + ADX_WDT_CONTROL);
-
-       platform_set_drvdata(pdev, wdt);
-       adx_wdt_dev = pdev;
-
-       ret = misc_register(&adx_wdt_miscdev);
-       if (ret) {
-               dev_err(&pdev->dev, "cannot register miscdev on minor %d "
-                               "(err=%d)\n", WATCHDOG_MINOR, ret);
-               return ret;
-       }
-
-       return 0;
-}
-
-static int __devexit adx_wdt_remove(struct platform_device *pdev)
-{
-       struct adx_wdt *wdt = platform_get_drvdata(pdev);
-
-       misc_deregister(&adx_wdt_miscdev);
-       adx_wdt_stop(wdt);
-       platform_set_drvdata(pdev, NULL);
-
-       return 0;
-}
-
-static void adx_wdt_shutdown(struct platform_device *pdev)
-{
-       struct adx_wdt *wdt = platform_get_drvdata(pdev);
-       adx_wdt_stop(wdt);
-}
-
-#ifdef CONFIG_PM
-static int adx_wdt_suspend(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct adx_wdt *wdt = platform_get_drvdata(pdev);
-
-       wdt->wake = (wdt->state == WDT_STATE_START) ? 1 : 0;
-       adx_wdt_stop(wdt);
-
-       return 0;
-}
-
-static int adx_wdt_resume(struct device *dev)
-{
-       struct platform_device *pdev = to_platform_device(dev);
-       struct adx_wdt *wdt = platform_get_drvdata(pdev);
-
-       if (wdt->wake)
-               adx_wdt_start(wdt);
-
-       return 0;
-}
-
-static const struct dev_pm_ops adx_wdt_pm_ops = {
-       .suspend = adx_wdt_suspend,
-       .resume = adx_wdt_resume,
-};
-
-#  define ADX_WDT_PM_OPS       (&adx_wdt_pm_ops)
-#else
-#  define ADX_WDT_PM_OPS       NULL
-#endif
-
-static struct platform_driver adx_wdt_driver = {
-       .probe = adx_wdt_probe,
-       .remove = __devexit_p(adx_wdt_remove),
-       .shutdown = adx_wdt_shutdown,
-       .driver = {
-               .name = WATCHDOG_NAME,
-               .owner = THIS_MODULE,
-               .pm = ADX_WDT_PM_OPS,
-       },
-};
-
-static int __init adx_wdt_init(void)
-{
-       return platform_driver_register(&adx_wdt_driver);
-}
-
-static void __exit adx_wdt_exit(void)
-{
-       platform_driver_unregister(&adx_wdt_driver);
-}
-
-module_init(adx_wdt_init);
-module_exit(adx_wdt_exit);
-
-MODULE_DESCRIPTION("Avionic Design Xanthos Watchdog Driver");
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Thierry Reding <thierry.reding@avionic-design.de>");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
index 5de7e4f..a79e384 100644 (file)
@@ -401,8 +401,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
 
        dev_info(dev, "watchdog %sactive, reset %sabled, irq %sabled\n",
                 (wtcon & S3C2410_WTCON_ENABLE) ?  "" : "in",
-                (wtcon & S3C2410_WTCON_RSTEN) ? "" : "dis",
-                (wtcon & S3C2410_WTCON_INTEN) ? "" : "en");
+                (wtcon & S3C2410_WTCON_RSTEN) ? "en" : "dis",
+                (wtcon & S3C2410_WTCON_INTEN) ? "en" : "dis");
 
        return 0;
 
index 7be3855..e789a47 100644 (file)
@@ -150,7 +150,7 @@ static int wm831x_wdt_set_timeout(struct watchdog_device *wdt_dev,
                if (wm831x_wdt_cfgs[i].time == timeout)
                        break;
        if (i == ARRAY_SIZE(wm831x_wdt_cfgs))
-               ret = -EINVAL;
+               return -EINVAL;
 
        ret = wm831x_reg_unlock(wm831x);
        if (ret == 0) {
index a767884..31ab82f 100644 (file)
@@ -501,7 +501,7 @@ EXPORT_SYMBOL_GPL(balloon_set_new_target);
  * alloc_xenballooned_pages - get pages that have been ballooned out
  * @nr_pages: Number of pages to get
  * @pages: pages returned
- * @highmem: highmem or lowmem pages
+ * @highmem: allow highmem pages
  * @return 0 on success, error otherwise
  */
 int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
@@ -511,7 +511,7 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages, bool highmem)
        mutex_lock(&balloon_mutex);
        while (pgno < nr_pages) {
                page = balloon_retrieve(highmem);
-               if (page && PageHighMem(page) == highmem) {
+               if (page && (highmem || !PageHighMem(page))) {
                        pages[pgno++] = page;
                } else {
                        enum bp_state st;
index f6832f4..e1c4c6e 100644 (file)
@@ -135,7 +135,7 @@ static int add_grefs(struct ioctl_gntalloc_alloc_gref *op,
                /* Grant foreign access to the page. */
                gref->gref_id = gnttab_grant_foreign_access(op->domid,
                        pfn_to_mfn(page_to_pfn(gref->page)), readonly);
-               if (gref->gref_id < 0) {
+               if ((int)gref->gref_id < 0) {
                        rc = gref->gref_id;
                        goto undo;
                }
@@ -280,7 +280,7 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv,
                goto out;
        }
 
-       gref_ids = kzalloc(sizeof(gref_ids[0]) * op.count, GFP_TEMPORARY);
+       gref_ids = kcalloc(op.count, sizeof(gref_ids[0]), GFP_TEMPORARY);
        if (!gref_ids) {
                rc = -ENOMEM;
                goto out;
index 3987132..afca14d 100644 (file)
@@ -114,11 +114,11 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)
        if (NULL == add)
                return NULL;
 
-       add->grants    = kzalloc(sizeof(add->grants[0])    * count, GFP_KERNEL);
-       add->map_ops   = kzalloc(sizeof(add->map_ops[0])   * count, GFP_KERNEL);
-       add->unmap_ops = kzalloc(sizeof(add->unmap_ops[0]) * count, GFP_KERNEL);
-       add->kmap_ops  = kzalloc(sizeof(add->kmap_ops[0])  * count, GFP_KERNEL);
-       add->pages     = kzalloc(sizeof(add->pages[0])     * count, GFP_KERNEL);
+       add->grants    = kcalloc(count, sizeof(add->grants[0]), GFP_KERNEL);
+       add->map_ops   = kcalloc(count, sizeof(add->map_ops[0]), GFP_KERNEL);
+       add->unmap_ops = kcalloc(count, sizeof(add->unmap_ops[0]), GFP_KERNEL);
+       add->kmap_ops  = kcalloc(count, sizeof(add->kmap_ops[0]), GFP_KERNEL);
+       add->pages     = kcalloc(count, sizeof(add->pages[0]), GFP_KERNEL);
        if (NULL == add->grants    ||
            NULL == add->map_ops   ||
            NULL == add->unmap_ops ||
index 81c3ce6..1906125 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/vmalloc.h>
 #include <linux/export.h>
 #include <asm/xen/hypervisor.h>
+#include <asm/xen/page.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/event_channel.h>
 #include <xen/events.h>
@@ -436,19 +437,20 @@ EXPORT_SYMBOL_GPL(xenbus_free_evtchn);
 int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
 {
        struct gnttab_map_grant_ref op = {
-               .flags = GNTMAP_host_map,
+               .flags = GNTMAP_host_map | GNTMAP_contains_pte,
                .ref   = gnt_ref,
                .dom   = dev->otherend_id,
        };
        struct vm_struct *area;
+       pte_t *pte;
 
        *vaddr = NULL;
 
-       area = alloc_vm_area(PAGE_SIZE);
+       area = alloc_vm_area(PAGE_SIZE, &pte);
        if (!area)
                return -ENOMEM;
 
-       op.host_addr = (unsigned long)area->addr;
+       op.host_addr = arbitrary_virt_to_machine(pte).maddr;
 
        if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
                BUG();
@@ -527,6 +529,7 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
        struct gnttab_unmap_grant_ref op = {
                .host_addr = (unsigned long)vaddr,
        };
+       unsigned int level;
 
        /* It'd be nice if linux/vmalloc.h provided a find_vm_area(void *addr)
         * method so that we don't have to muck with vmalloc internals here.
@@ -548,6 +551,8 @@ int xenbus_unmap_ring_vfree(struct xenbus_device *dev, void *vaddr)
        }
 
        op.handle = (grant_handle_t)area->phys_addr;
+       op.host_addr = arbitrary_virt_to_machine(
+               lookup_address((unsigned long)vaddr, &level)).maddr;
 
        if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
                BUG();
index 41c93c7..b1fe82c 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -337,7 +337,7 @@ static void bio_fs_destructor(struct bio *bio)
  *     RETURNS:
  *     Pointer to new bio on success, NULL on failure.
  */
-struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs)
+struct bio *bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
        struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
 
@@ -365,7 +365,7 @@ static void bio_kmalloc_destructor(struct bio *bio)
  *   %__GFP_WAIT, the allocation is guaranteed to succeed.
  *
  **/
-struct bio *bio_kmalloc(gfp_t gfp_mask, int nr_iovecs)
+struct bio *bio_kmalloc(gfp_t gfp_mask, unsigned int nr_iovecs)
 {
        struct bio *bio;
 
@@ -696,7 +696,8 @@ static void bio_free_map_data(struct bio_map_data *bmd)
        kfree(bmd);
 }
 
-static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count,
+static struct bio_map_data *bio_alloc_map_data(int nr_segs,
+                                              unsigned int iov_count,
                                               gfp_t gfp_mask)
 {
        struct bio_map_data *bmd;
index 8855aad..22c64ff 100644 (file)
@@ -683,7 +683,7 @@ static int inode_to_path(u64 inum, struct btrfs_inode_ref *iref,
                return PTR_ERR(fspath);
 
        if (fspath > fspath_min) {
-               ipath->fspath->val[i] = (u64)fspath;
+               ipath->fspath->val[i] = (u64)(unsigned long)fspath;
                ++ipath->fspath->elem_cnt;
                ipath->fspath->bytes_left = fspath - fspath_min;
        } else {
index 5a5d325..634608d 100644 (file)
@@ -147,14 +147,12 @@ struct btrfs_inode {
         * the btrfs file release call will add this inode to the
         * ordered operations list so that we make sure to flush out any
         * new data the application may have written before commit.
-        *
-        * yes, its silly to have a single bitflag, but we might grow more
-        * of these.
         */
        unsigned ordered_data_close:1;
        unsigned orphan_meta_reserved:1;
        unsigned dummy_inode:1;
        unsigned in_defrag:1;
+       unsigned delalloc_meta_reserved:1;
 
        /*
         * always compress this one file
index 0fe615e..dede441 100644 (file)
@@ -514,10 +514,25 @@ static inline int should_cow_block(struct btrfs_trans_handle *trans,
                                   struct btrfs_root *root,
                                   struct extent_buffer *buf)
 {
+       /* ensure we can see the force_cow */
+       smp_rmb();
+
+       /*
+        * We do not need to cow a block if
+        * 1) this block is not created or changed in this transaction;
+        * 2) this block does not belong to TREE_RELOC tree;
+        * 3) the root is not forced COW.
+        *
+        * What is forced COW:
+        *    when we create snapshot during commiting the transaction,
+        *    after we've finished coping src root, we must COW the shared
+        *    block to ensure the metadata consistency.
+        */
        if (btrfs_header_generation(buf) == trans->transid &&
            !btrfs_header_flag(buf, BTRFS_HEADER_FLAG_WRITTEN) &&
            !(root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID &&
-             btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)))
+             btrfs_header_flag(buf, BTRFS_HEADER_FLAG_RELOC)) &&
+           !root->force_cow)
                return 0;
        return 1;
 }
index b9ba59f..50634ab 100644 (file)
@@ -848,7 +848,8 @@ struct btrfs_free_cluster {
 enum btrfs_caching_type {
        BTRFS_CACHE_NO          = 0,
        BTRFS_CACHE_STARTED     = 1,
-       BTRFS_CACHE_FINISHED    = 2,
+       BTRFS_CACHE_FAST        = 2,
+       BTRFS_CACHE_FINISHED    = 3,
 };
 
 enum btrfs_disk_cache_state {
@@ -1271,6 +1272,8 @@ struct btrfs_root {
         * for stat.  It may be used for more later
         */
        dev_t anon_dev;
+
+       int force_cow;
 };
 
 struct btrfs_ioctl_defrag_range_args {
@@ -2366,6 +2369,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root,
 int btrfs_block_rsv_refill(struct btrfs_root *root,
                          struct btrfs_block_rsv *block_rsv,
                          u64 min_reserved);
+int btrfs_block_rsv_refill_noflush(struct btrfs_root *root,
+                                  struct btrfs_block_rsv *block_rsv,
+                                  u64 min_reserved);
 int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
                            struct btrfs_block_rsv *dst_rsv,
                            u64 num_bytes);
index 3a1b939..5b16357 100644 (file)
@@ -617,12 +617,14 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root,
 static int btrfs_delayed_inode_reserve_metadata(
                                        struct btrfs_trans_handle *trans,
                                        struct btrfs_root *root,
+                                       struct inode *inode,
                                        struct btrfs_delayed_node *node)
 {
        struct btrfs_block_rsv *src_rsv;
        struct btrfs_block_rsv *dst_rsv;
        u64 num_bytes;
        int ret;
+       int release = false;
 
        src_rsv = trans->block_rsv;
        dst_rsv = &root->fs_info->delayed_block_rsv;
@@ -652,12 +654,65 @@ static int btrfs_delayed_inode_reserve_metadata(
                if (!ret)
                        node->bytes_reserved = num_bytes;
                return ret;
+       } else if (src_rsv == &root->fs_info->delalloc_block_rsv) {
+               spin_lock(&BTRFS_I(inode)->lock);
+               if (BTRFS_I(inode)->delalloc_meta_reserved) {
+                       BTRFS_I(inode)->delalloc_meta_reserved = 0;
+                       spin_unlock(&BTRFS_I(inode)->lock);
+                       release = true;
+                       goto migrate;
+               }
+               spin_unlock(&BTRFS_I(inode)->lock);
+
+               /* Ok we didn't have space pre-reserved.  This shouldn't happen
+                * too often but it can happen if we do delalloc to an existing
+                * inode which gets dirtied because of the time update, and then
+                * isn't touched again until after the transaction commits and
+                * then we try to write out the data.  First try to be nice and
+                * reserve something strictly for us.  If not be a pain and try
+                * to steal from the delalloc block rsv.
+                */
+               ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes);
+               if (!ret)
+                       goto out;
+
+               ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
+               if (!ret)
+                       goto out;
+
+               /*
+                * Ok this is a problem, let's just steal from the global rsv
+                * since this really shouldn't happen that often.
+                */
+               WARN_ON(1);
+               ret = btrfs_block_rsv_migrate(&root->fs_info->global_block_rsv,
+                                             dst_rsv, num_bytes);
+               goto out;
        }
 
+migrate:
        ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
+
+out:
+       /*
+        * Migrate only takes a reservation, it doesn't touch the size of the
+        * block_rsv.  This is to simplify people who don't normally have things
+        * migrated from their block rsv.  If they go to release their
+        * reservation, that will decrease the size as well, so if migrate
+        * reduced size we'd end up with a negative size.  But for the
+        * delalloc_meta_reserved stuff we will only know to drop 1 reservation,
+        * but we could in fact do this reserve/migrate dance several times
+        * between the time we did the original reservation and we'd clean it
+        * up.  So to take care of this, release the space for the meta
+        * reservation here.  I think it may be time for a documentation page on
+        * how block rsvs. work.
+        */
        if (!ret)
                node->bytes_reserved = num_bytes;
 
+       if (release)
+               btrfs_block_rsv_release(root, src_rsv, num_bytes);
+
        return ret;
 }
 
@@ -1708,7 +1763,8 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,
                goto release_node;
        }
 
-       ret = btrfs_delayed_inode_reserve_metadata(trans, root, delayed_node);
+       ret = btrfs_delayed_inode_reserve_metadata(trans, root, inode,
+                                                  delayed_node);
        if (ret)
                goto release_node;
 
index 102c176..632f8f3 100644 (file)
@@ -620,7 +620,7 @@ out:
 
 static int btree_io_failed_hook(struct bio *failed_bio,
                         struct page *page, u64 start, u64 end,
-                        u64 mirror_num, struct extent_state *state)
+                        int mirror_num, struct extent_state *state)
 {
        struct extent_io_tree *tree;
        unsigned long len;
@@ -1890,31 +1890,32 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        u64 features;
        struct btrfs_key location;
        struct buffer_head *bh;
-       struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root),
-                                                GFP_NOFS);
-       struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root),
-                                                GFP_NOFS);
+       struct btrfs_super_block *disk_super;
        struct btrfs_root *tree_root = btrfs_sb(sb);
-       struct btrfs_fs_info *fs_info = NULL;
-       struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root),
-                                               GFP_NOFS);
-       struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root),
-                                             GFP_NOFS);
+       struct btrfs_fs_info *fs_info = tree_root->fs_info;
+       struct btrfs_root *extent_root;
+       struct btrfs_root *csum_root;
+       struct btrfs_root *chunk_root;
+       struct btrfs_root *dev_root;
        struct btrfs_root *log_tree_root;
-
        int ret;
        int err = -EINVAL;
        int num_backups_tried = 0;
        int backup_index = 0;
 
-       struct btrfs_super_block *disk_super;
+       extent_root = fs_info->extent_root =
+               kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       csum_root = fs_info->csum_root =
+               kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       chunk_root = fs_info->chunk_root =
+               kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       dev_root = fs_info->dev_root =
+               kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
 
-       if (!extent_root || !tree_root || !tree_root->fs_info ||
-           !chunk_root || !dev_root || !csum_root) {
+       if (!extent_root || !csum_root || !chunk_root || !dev_root) {
                err = -ENOMEM;
                goto fail;
        }
-       fs_info = tree_root->fs_info;
 
        ret = init_srcu_struct(&fs_info->subvol_srcu);
        if (ret) {
@@ -1954,12 +1955,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        mutex_init(&fs_info->reloc_mutex);
 
        init_completion(&fs_info->kobj_unregister);
-       fs_info->tree_root = tree_root;
-       fs_info->extent_root = extent_root;
-       fs_info->csum_root = csum_root;
-       fs_info->chunk_root = chunk_root;
-       fs_info->dev_root = dev_root;
-       fs_info->fs_devices = fs_devices;
        INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots);
        INIT_LIST_HEAD(&fs_info->space_info);
        btrfs_mapping_init(&fs_info->mapping_tree);
@@ -2465,21 +2460,20 @@ fail_sb_buffer:
        btrfs_stop_workers(&fs_info->caching_workers);
 fail_alloc:
 fail_iput:
+       btrfs_mapping_tree_free(&fs_info->mapping_tree);
+
        invalidate_inode_pages2(fs_info->btree_inode->i_mapping);
        iput(fs_info->btree_inode);
-
-       btrfs_close_devices(fs_info->fs_devices);
-       btrfs_mapping_tree_free(&fs_info->mapping_tree);
 fail_bdi:
        bdi_destroy(&fs_info->bdi);
 fail_srcu:
        cleanup_srcu_struct(&fs_info->subvol_srcu);
 fail:
+       btrfs_close_devices(fs_info->fs_devices);
        free_fs_info(fs_info);
        return ERR_PTR(err);
 
 recovery_tree_root:
-
        if (!btrfs_test_opt(tree_root, RECOVERY))
                goto fail_tree_roots;
 
@@ -2579,22 +2573,10 @@ static int write_dev_supers(struct btrfs_device *device,
        int errors = 0;
        u32 crc;
        u64 bytenr;
-       int last_barrier = 0;
 
        if (max_mirrors == 0)
                max_mirrors = BTRFS_SUPER_MIRROR_MAX;
 
-       /* make sure only the last submit_bh does a barrier */
-       if (do_barriers) {
-               for (i = 0; i < max_mirrors; i++) {
-                       bytenr = btrfs_sb_offset(i);
-                       if (bytenr + BTRFS_SUPER_INFO_SIZE >=
-                           device->total_bytes)
-                               break;
-                       last_barrier = i;
-               }
-       }
-
        for (i = 0; i < max_mirrors; i++) {
                bytenr = btrfs_sb_offset(i);
                if (bytenr + BTRFS_SUPER_INFO_SIZE >= device->total_bytes)
@@ -2640,17 +2622,136 @@ static int write_dev_supers(struct btrfs_device *device,
                        bh->b_end_io = btrfs_end_buffer_write_sync;
                }
 
-               if (i == last_barrier && do_barriers)
-                       ret = submit_bh(WRITE_FLUSH_FUA, bh);
-               else
-                       ret = submit_bh(WRITE_SYNC, bh);
-
+               /*
+                * we fua the first super.  The others we allow
+                * to go down lazy.
+                */
+               ret = submit_bh(WRITE_FUA, bh);
                if (ret)
                        errors++;
        }
        return errors < i ? 0 : -1;
 }
 
+/*
+ * endio for the write_dev_flush, this will wake anyone waiting
+ * for the barrier when it is done
+ */
+static void btrfs_end_empty_barrier(struct bio *bio, int err)
+{
+       if (err) {
+               if (err == -EOPNOTSUPP)
+                       set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
+               clear_bit(BIO_UPTODATE, &bio->bi_flags);
+       }
+       if (bio->bi_private)
+               complete(bio->bi_private);
+       bio_put(bio);
+}
+
+/*
+ * trigger flushes for one the devices.  If you pass wait == 0, the flushes are
+ * sent down.  With wait == 1, it waits for the previous flush.
+ *
+ * any device where the flush fails with eopnotsupp are flagged as not-barrier
+ * capable
+ */
+static int write_dev_flush(struct btrfs_device *device, int wait)
+{
+       struct bio *bio;
+       int ret = 0;
+
+       if (device->nobarriers)
+               return 0;
+
+       if (wait) {
+               bio = device->flush_bio;
+               if (!bio)
+                       return 0;
+
+               wait_for_completion(&device->flush_wait);
+
+               if (bio_flagged(bio, BIO_EOPNOTSUPP)) {
+                       printk("btrfs: disabling barriers on dev %s\n",
+                              device->name);
+                       device->nobarriers = 1;
+               }
+               if (!bio_flagged(bio, BIO_UPTODATE)) {
+                       ret = -EIO;
+               }
+
+               /* drop the reference from the wait == 0 run */
+               bio_put(bio);
+               device->flush_bio = NULL;
+
+               return ret;
+       }
+
+       /*
+        * one reference for us, and we leave it for the
+        * caller
+        */
+       device->flush_bio = NULL;;
+       bio = bio_alloc(GFP_NOFS, 0);
+       if (!bio)
+               return -ENOMEM;
+
+       bio->bi_end_io = btrfs_end_empty_barrier;
+       bio->bi_bdev = device->bdev;
+       init_completion(&device->flush_wait);
+       bio->bi_private = &device->flush_wait;
+       device->flush_bio = bio;
+
+       bio_get(bio);
+       submit_bio(WRITE_FLUSH, bio);
+
+       return 0;
+}
+
+/*
+ * send an empty flush down to each device in parallel,
+ * then wait for them
+ */
+static int barrier_all_devices(struct btrfs_fs_info *info)
+{
+       struct list_head *head;
+       struct btrfs_device *dev;
+       int errors = 0;
+       int ret;
+
+       /* send down all the barriers */
+       head = &info->fs_devices->devices;
+       list_for_each_entry_rcu(dev, head, dev_list) {
+               if (!dev->bdev) {
+                       errors++;
+                       continue;
+               }
+               if (!dev->in_fs_metadata || !dev->writeable)
+                       continue;
+
+               ret = write_dev_flush(dev, 0);
+               if (ret)
+                       errors++;
+       }
+
+       /* wait for all the barriers */
+       list_for_each_entry_rcu(dev, head, dev_list) {
+               if (!dev->bdev) {
+                       errors++;
+                       continue;
+               }
+               if (!dev->in_fs_metadata || !dev->writeable)
+                       continue;
+
+               ret = write_dev_flush(dev, 1);
+               if (ret)
+                       errors++;
+       }
+       if (errors)
+               return -EIO;
+       return 0;
+}
+
 int write_all_supers(struct btrfs_root *root, int max_mirrors)
 {
        struct list_head *head;
@@ -2672,6 +2773,10 @@ int write_all_supers(struct btrfs_root *root, int max_mirrors)
 
        mutex_lock(&root->fs_info->fs_devices->device_list_mutex);
        head = &root->fs_info->fs_devices->devices;
+
+       if (do_barriers)
+               barrier_all_devices(root->fs_info);
+
        list_for_each_entry_rcu(dev, head, dev_list) {
                if (!dev->bdev) {
                        total_errors++;
index 9879bd4..f0d5718 100644 (file)
@@ -467,13 +467,59 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
                             struct btrfs_root *root,
                             int load_cache_only)
 {
+       DEFINE_WAIT(wait);
        struct btrfs_fs_info *fs_info = cache->fs_info;
        struct btrfs_caching_control *caching_ctl;
        int ret = 0;
 
-       smp_mb();
-       if (cache->cached != BTRFS_CACHE_NO)
+       caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS);
+       BUG_ON(!caching_ctl);
+
+       INIT_LIST_HEAD(&caching_ctl->list);
+       mutex_init(&caching_ctl->mutex);
+       init_waitqueue_head(&caching_ctl->wait);
+       caching_ctl->block_group = cache;
+       caching_ctl->progress = cache->key.objectid;
+       atomic_set(&caching_ctl->count, 1);
+       caching_ctl->work.func = caching_thread;
+
+       spin_lock(&cache->lock);
+       /*
+        * This should be a rare occasion, but this could happen I think in the
+        * case where one thread starts to load the space cache info, and then
+        * some other thread starts a transaction commit which tries to do an
+        * allocation while the other thread is still loading the space cache
+        * info.  The previous loop should have kept us from choosing this block
+        * group, but if we've moved to the state where we will wait on caching
+        * block groups we need to first check if we're doing a fast load here,
+        * so we can wait for it to finish, otherwise we could end up allocating
+        * from a block group who's cache gets evicted for one reason or
+        * another.
+        */
+       while (cache->cached == BTRFS_CACHE_FAST) {
+               struct btrfs_caching_control *ctl;
+
+               ctl = cache->caching_ctl;
+               atomic_inc(&ctl->count);
+               prepare_to_wait(&ctl->wait, &wait, TASK_UNINTERRUPTIBLE);
+               spin_unlock(&cache->lock);
+
+               schedule();
+
+               finish_wait(&ctl->wait, &wait);
+               put_caching_control(ctl);
+               spin_lock(&cache->lock);
+       }
+
+       if (cache->cached != BTRFS_CACHE_NO) {
+               spin_unlock(&cache->lock);
+               kfree(caching_ctl);
                return 0;
+       }
+       WARN_ON(cache->caching_ctl);
+       cache->caching_ctl = caching_ctl;
+       cache->cached = BTRFS_CACHE_FAST;
+       spin_unlock(&cache->lock);
 
        /*
         * We can't do the read from on-disk cache during a commit since we need
@@ -484,56 +530,51 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
        if (trans && (!trans->transaction->in_commit) &&
            (root && root != root->fs_info->tree_root) &&
            btrfs_test_opt(root, SPACE_CACHE)) {
-               spin_lock(&cache->lock);
-               if (cache->cached != BTRFS_CACHE_NO) {
-                       spin_unlock(&cache->lock);
-                       return 0;
-               }
-               cache->cached = BTRFS_CACHE_STARTED;
-               spin_unlock(&cache->lock);
-
                ret = load_free_space_cache(fs_info, cache);
 
                spin_lock(&cache->lock);
                if (ret == 1) {
+                       cache->caching_ctl = NULL;
                        cache->cached = BTRFS_CACHE_FINISHED;
                        cache->last_byte_to_unpin = (u64)-1;
                } else {
-                       cache->cached = BTRFS_CACHE_NO;
+                       if (load_cache_only) {
+                               cache->caching_ctl = NULL;
+                               cache->cached = BTRFS_CACHE_NO;
+                       } else {
+                               cache->cached = BTRFS_CACHE_STARTED;
+                       }
                }
                spin_unlock(&cache->lock);
+               wake_up(&caching_ctl->wait);
                if (ret == 1) {
+                       put_caching_control(caching_ctl);
                        free_excluded_extents(fs_info->extent_root, cache);
                        return 0;
                }
+       } else {
+               /*
+                * We are not going to do the fast caching, set cached to the
+                * appropriate value and wakeup any waiters.
+                */
+               spin_lock(&cache->lock);
+               if (load_cache_only) {
+                       cache->caching_ctl = NULL;
+                       cache->cached = BTRFS_CACHE_NO;
+               } else {
+                       cache->cached = BTRFS_CACHE_STARTED;
+               }
+               spin_unlock(&cache->lock);
+               wake_up(&caching_ctl->wait);
        }
 
-       if (load_cache_only)
-               return 0;
-
-       caching_ctl = kzalloc(sizeof(*caching_ctl), GFP_NOFS);
-       BUG_ON(!caching_ctl);
-
-       INIT_LIST_HEAD(&caching_ctl->list);
-       mutex_init(&caching_ctl->mutex);
-       init_waitqueue_head(&caching_ctl->wait);
-       caching_ctl->block_group = cache;
-       caching_ctl->progress = cache->key.objectid;
-       /* one for caching kthread, one for caching block group list */
-       atomic_set(&caching_ctl->count, 2);
-       caching_ctl->work.func = caching_thread;
-
-       spin_lock(&cache->lock);
-       if (cache->cached != BTRFS_CACHE_NO) {
-               spin_unlock(&cache->lock);
-               kfree(caching_ctl);
+       if (load_cache_only) {
+               put_caching_control(caching_ctl);
                return 0;
        }
-       cache->caching_ctl = caching_ctl;
-       cache->cached = BTRFS_CACHE_STARTED;
-       spin_unlock(&cache->lock);
 
        down_write(&fs_info->extent_commit_sem);
+       atomic_inc(&caching_ctl->count);
        list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups);
        up_write(&fs_info->extent_commit_sem);
 
@@ -3797,16 +3838,16 @@ void btrfs_free_block_rsv(struct btrfs_root *root,
        kfree(rsv);
 }
 
-int btrfs_block_rsv_add(struct btrfs_root *root,
-                       struct btrfs_block_rsv *block_rsv,
-                       u64 num_bytes)
+static inline int __block_rsv_add(struct btrfs_root *root,
+                                 struct btrfs_block_rsv *block_rsv,
+                                 u64 num_bytes, int flush)
 {
        int ret;
 
        if (num_bytes == 0)
                return 0;
 
-       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 1);
+       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
        if (!ret) {
                block_rsv_add_bytes(block_rsv, num_bytes, 1);
                return 0;
@@ -3815,22 +3856,18 @@ int btrfs_block_rsv_add(struct btrfs_root *root,
        return ret;
 }
 
+int btrfs_block_rsv_add(struct btrfs_root *root,
+                       struct btrfs_block_rsv *block_rsv,
+                       u64 num_bytes)
+{
+       return __block_rsv_add(root, block_rsv, num_bytes, 1);
+}
+
 int btrfs_block_rsv_add_noflush(struct btrfs_root *root,
                                struct btrfs_block_rsv *block_rsv,
                                u64 num_bytes)
 {
-       int ret;
-
-       if (num_bytes == 0)
-               return 0;
-
-       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 0);
-       if (!ret) {
-               block_rsv_add_bytes(block_rsv, num_bytes, 1);
-               return 0;
-       }
-
-       return ret;
+       return __block_rsv_add(root, block_rsv, num_bytes, 0);
 }
 
 int btrfs_block_rsv_check(struct btrfs_root *root,
@@ -3851,9 +3888,9 @@ int btrfs_block_rsv_check(struct btrfs_root *root,
        return ret;
 }
 
-int btrfs_block_rsv_refill(struct btrfs_root *root,
-                         struct btrfs_block_rsv *block_rsv,
-                         u64 min_reserved)
+static inline int __btrfs_block_rsv_refill(struct btrfs_root *root,
+                                          struct btrfs_block_rsv *block_rsv,
+                                          u64 min_reserved, int flush)
 {
        u64 num_bytes = 0;
        int ret = -ENOSPC;
@@ -3872,7 +3909,7 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
        if (!ret)
                return 0;
 
-       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 1);
+       ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush);
        if (!ret) {
                block_rsv_add_bytes(block_rsv, num_bytes, 0);
                return 0;
@@ -3881,6 +3918,20 @@ int btrfs_block_rsv_refill(struct btrfs_root *root,
        return ret;
 }
 
+int btrfs_block_rsv_refill(struct btrfs_root *root,
+                          struct btrfs_block_rsv *block_rsv,
+                          u64 min_reserved)
+{
+       return __btrfs_block_rsv_refill(root, block_rsv, min_reserved, 1);
+}
+
+int btrfs_block_rsv_refill_noflush(struct btrfs_root *root,
+                                  struct btrfs_block_rsv *block_rsv,
+                                  u64 min_reserved)
+{
+       return __btrfs_block_rsv_refill(root, block_rsv, min_reserved, 0);
+}
+
 int btrfs_block_rsv_migrate(struct btrfs_block_rsv *src_rsv,
                            struct btrfs_block_rsv *dst_rsv,
                            u64 num_bytes)
@@ -4064,23 +4115,30 @@ int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans,
  */
 static unsigned drop_outstanding_extent(struct inode *inode)
 {
+       unsigned drop_inode_space = 0;
        unsigned dropped_extents = 0;
 
        BUG_ON(!BTRFS_I(inode)->outstanding_extents);
        BTRFS_I(inode)->outstanding_extents--;
 
+       if (BTRFS_I(inode)->outstanding_extents == 0 &&
+           BTRFS_I(inode)->delalloc_meta_reserved) {
+               drop_inode_space = 1;
+               BTRFS_I(inode)->delalloc_meta_reserved = 0;
+       }
+
        /*
         * If we have more or the same amount of outsanding extents than we have
         * reserved then we need to leave the reserved extents count alone.
         */
        if (BTRFS_I(inode)->outstanding_extents >=
            BTRFS_I(inode)->reserved_extents)
-               return 0;
+               return drop_inode_space;
 
        dropped_extents = BTRFS_I(inode)->reserved_extents -
                BTRFS_I(inode)->outstanding_extents;
        BTRFS_I(inode)->reserved_extents -= dropped_extents;
-       return dropped_extents;
+       return dropped_extents + drop_inode_space;
 }
 
 /**
@@ -4166,9 +4224,18 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
                nr_extents = BTRFS_I(inode)->outstanding_extents -
                        BTRFS_I(inode)->reserved_extents;
                BTRFS_I(inode)->reserved_extents += nr_extents;
+       }
 
-               to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents);
+       /*
+        * Add an item to reserve for updating the inode when we complete the
+        * delalloc io.
+        */
+       if (!BTRFS_I(inode)->delalloc_meta_reserved) {
+               nr_extents++;
+               BTRFS_I(inode)->delalloc_meta_reserved = 1;
        }
+
+       to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents);
        to_reserve += calc_csum_metadata_size(inode, num_bytes, 1);
        spin_unlock(&BTRFS_I(inode)->lock);
 
@@ -5166,13 +5233,15 @@ search:
                }
 
 have_block_group:
-               if (unlikely(block_group->cached == BTRFS_CACHE_NO)) {
+               cached = block_group_cache_done(block_group);
+               if (unlikely(!cached)) {
                        u64 free_percent;
 
+                       found_uncached_bg = true;
                        ret = cache_block_group(block_group, trans,
                                                orig_root, 1);
                        if (block_group->cached == BTRFS_CACHE_FINISHED)
-                               goto have_block_group;
+                               goto alloc;
 
                        free_percent = btrfs_block_group_used(&block_group->item);
                        free_percent *= 100;
@@ -5194,7 +5263,6 @@ have_block_group:
                                                        orig_root, 0);
                                BUG_ON(ret);
                        }
-                       found_uncached_bg = true;
 
                        /*
                         * If loop is set for cached only, try the next block
@@ -5204,17 +5272,14 @@ have_block_group:
                                goto loop;
                }
 
-               cached = block_group_cache_done(block_group);
-               if (unlikely(!cached))
-                       found_uncached_bg = true;
-
+alloc:
                if (unlikely(block_group->ro))
                        goto loop;
 
                spin_lock(&block_group->free_space_ctl->tree_lock);
                if (cached &&
                    block_group->free_space_ctl->free_space <
-                   num_bytes + empty_size) {
+                   num_bytes + empty_cluster + empty_size) {
                        spin_unlock(&block_group->free_space_ctl->tree_lock);
                        goto loop;
                }
@@ -5235,12 +5300,10 @@ have_block_group:
                         * people trying to start a new cluster
                         */
                        spin_lock(&last_ptr->refill_lock);
-                       if (last_ptr->block_group &&
-                           (last_ptr->block_group->ro ||
-                           !block_group_bits(last_ptr->block_group, data))) {
-                               offset = 0;
+                       if (!last_ptr->block_group ||
+                           last_ptr->block_group->ro ||
+                           !block_group_bits(last_ptr->block_group, data))
                                goto refill_cluster;
-                       }
 
                        offset = btrfs_alloc_from_cluster(block_group, last_ptr,
                                                 num_bytes, search_start);
@@ -5291,7 +5354,7 @@ refill_cluster:
                        /* allocate a cluster in this block group */
                        ret = btrfs_find_space_cluster(trans, root,
                                               block_group, last_ptr,
-                                              offset, num_bytes,
+                                              search_start, num_bytes,
                                               empty_cluster + empty_size);
                        if (ret == 0) {
                                /*
index 1f87c4d..be1bf62 100644 (file)
@@ -2285,16 +2285,22 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                                clean_io_failure(start, page);
                }
                if (!uptodate) {
-                       u64 failed_mirror;
-                       failed_mirror = (u64)bio->bi_bdev;
-                       if (tree->ops && tree->ops->readpage_io_failed_hook)
-                               ret = tree->ops->readpage_io_failed_hook(
-                                               bio, page, start, end,
-                                               failed_mirror, state);
-                       else
-                               ret = bio_readpage_error(bio, page, start, end,
-                                                        failed_mirror, NULL);
+                       int failed_mirror;
+                       failed_mirror = (int)(unsigned long)bio->bi_bdev;
+                       /*
+                        * The generic bio_readpage_error handles errors the
+                        * following way: If possible, new read requests are
+                        * created and submitted and will end up in
+                        * end_bio_extent_readpage as well (if we're lucky, not
+                        * in the !uptodate case). In that case it returns 0 and
+                        * we just go on with the next page in our bio. If it
+                        * can't handle the error it will return -EIO and we
+                        * remain responsible for that page.
+                        */
+                       ret = bio_readpage_error(bio, page, start, end,
+                                                       failed_mirror, NULL);
                        if (ret == 0) {
+error_handled:
                                uptodate =
                                        test_bit(BIO_UPTODATE, &bio->bi_flags);
                                if (err)
@@ -2302,6 +2308,13 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                                uncache_state(&cached);
                                continue;
                        }
+                       if (tree->ops && tree->ops->readpage_io_failed_hook) {
+                               ret = tree->ops->readpage_io_failed_hook(
+                                                       bio, page, start, end,
+                                                       failed_mirror, state);
+                               if (ret == 0)
+                                       goto error_handled;
+                       }
                }
 
                if (uptodate) {
@@ -3366,6 +3379,9 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                return -ENOMEM;
        path->leave_spinning = 1;
 
+       start = ALIGN(start, BTRFS_I(inode)->root->sectorsize);
+       len = ALIGN(len, BTRFS_I(inode)->root->sectorsize);
+
        /*
         * lookup the last file extent.  We're not using i_size here
         * because there might be preallocation past i_size
@@ -3413,7 +3429,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0,
                         &cached_state, GFP_NOFS);
 
-       em = get_extent_skip_holes(inode, off, last_for_get_extent,
+       em = get_extent_skip_holes(inode, start, last_for_get_extent,
                                   get_extent);
        if (!em)
                goto out;
index feb9be0..7604c30 100644 (file)
@@ -70,7 +70,7 @@ struct extent_io_ops {
                              unsigned long bio_flags);
        int (*readpage_io_hook)(struct page *page, u64 start, u64 end);
        int (*readpage_io_failed_hook)(struct bio *bio, struct page *page,
-                                      u64 start, u64 end, u64 failed_mirror,
+                                      u64 start, u64 end, int failed_mirror,
                                       struct extent_state *state);
        int (*writepage_io_failed_hook)(struct bio *bio, struct page *page,
                                        u64 start, u64 end,
index 7a15fcf..ec23d43 100644 (file)
@@ -351,6 +351,11 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode,
                }
        }
 
+       for (i = 0; i < io_ctl->num_pages; i++) {
+               clear_page_dirty_for_io(io_ctl->pages[i]);
+               set_page_extent_mapped(io_ctl->pages[i]);
+       }
+
        return 0;
 }
 
@@ -537,6 +542,13 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl,
                            struct btrfs_free_space *entry, u8 *type)
 {
        struct btrfs_free_space_entry *e;
+       int ret;
+
+       if (!io_ctl->cur) {
+               ret = io_ctl_check_crc(io_ctl, io_ctl->index);
+               if (ret)
+                       return ret;
+       }
 
        e = io_ctl->cur;
        entry->offset = le64_to_cpu(e->offset);
@@ -550,10 +562,7 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl,
 
        io_ctl_unmap_page(io_ctl);
 
-       if (io_ctl->index >= io_ctl->num_pages)
-               return 0;
-
-       return io_ctl_check_crc(io_ctl, io_ctl->index);
+       return 0;
 }
 
 static int io_ctl_read_bitmap(struct io_ctl *io_ctl,
@@ -561,9 +570,6 @@ static int io_ctl_read_bitmap(struct io_ctl *io_ctl,
 {
        int ret;
 
-       if (io_ctl->cur && io_ctl->cur != io_ctl->orig)
-               io_ctl_unmap_page(io_ctl);
-
        ret = io_ctl_check_crc(io_ctl, io_ctl->index);
        if (ret)
                return ret;
@@ -699,6 +705,8 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode,
                num_entries--;
        }
 
+       io_ctl_unmap_page(&io_ctl);
+
        /*
         * We add the bitmaps at the end of the entries in order that
         * the bitmap entries are added to the cache.
@@ -1462,6 +1470,7 @@ static void add_new_bitmap(struct btrfs_free_space_ctl *ctl,
 {
        info->offset = offset_to_bitmap(ctl, offset);
        info->bytes = 0;
+       INIT_LIST_HEAD(&info->list);
        link_free_space(ctl, info);
        ctl->total_bitmaps++;
 
@@ -1841,7 +1850,13 @@ again:
                info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
                                          1, 0);
                if (!info) {
-                       WARN_ON(1);
+                       /* the tree logging code might be calling us before we
+                        * have fully loaded the free space rbtree for this
+                        * block group.  So it is possible the entry won't
+                        * be in the rbtree yet at all.  The caching code
+                        * will make sure not to put it in the rbtree if
+                        * the logging code has pinned it.
+                        */
                        goto out_lock;
                }
        }
@@ -2305,6 +2320,7 @@ again:
 
        if (!found) {
                start = i;
+               cluster->max_size = 0;
                found = true;
        }
 
@@ -2448,16 +2464,23 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
        struct btrfs_free_space *entry;
-       struct rb_node *node;
        int ret = -ENOSPC;
+       u64 bitmap_offset = offset_to_bitmap(ctl, offset);
 
        if (ctl->total_bitmaps == 0)
                return -ENOSPC;
 
        /*
-        * First check our cached list of bitmaps and see if there is an entry
-        * here that will work.
+        * The bitmap that covers offset won't be in the list unless offset
+        * is just its start offset.
         */
+       entry = list_first_entry(bitmaps, struct btrfs_free_space, list);
+       if (entry->offset != bitmap_offset) {
+               entry = tree_search_offset(ctl, bitmap_offset, 1, 0);
+               if (entry && list_empty(&entry->list))
+                       list_add(&entry->list, bitmaps);
+       }
+
        list_for_each_entry(entry, bitmaps, list) {
                if (entry->bytes < min_bytes)
                        continue;
@@ -2468,38 +2491,10 @@ setup_cluster_bitmap(struct btrfs_block_group_cache *block_group,
        }
 
        /*
-        * If we do have entries on our list and we are here then we didn't find
-        * anything, so go ahead and get the next entry after the last entry in
-        * this list and start the search from there.
+        * The bitmaps list has all the bitmaps that record free space
+        * starting after offset, so no more search is required.
         */
-       if (!list_empty(bitmaps)) {
-               entry = list_entry(bitmaps->prev, struct btrfs_free_space,
-                                  list);
-               node = rb_next(&entry->offset_index);
-               if (!node)
-                       return -ENOSPC;
-               entry = rb_entry(node, struct btrfs_free_space, offset_index);
-               goto search;
-       }
-
-       entry = tree_search_offset(ctl, offset_to_bitmap(ctl, offset), 0, 1);
-       if (!entry)
-               return -ENOSPC;
-
-search:
-       node = &entry->offset_index;
-       do {
-               entry = rb_entry(node, struct btrfs_free_space, offset_index);
-               node = rb_next(&entry->offset_index);
-               if (!entry->bitmap)
-                       continue;
-               if (entry->bytes < min_bytes)
-                       continue;
-               ret = btrfs_bitmap_cluster(block_group, entry, cluster, offset,
-                                          bytes, min_bytes);
-       } while (ret && node);
-
-       return ret;
+       return -ENOSPC;
 }
 
 /*
@@ -2517,8 +2512,8 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                             u64 offset, u64 bytes, u64 empty_size)
 {
        struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
-       struct list_head bitmaps;
        struct btrfs_free_space *entry, *tmp;
+       LIST_HEAD(bitmaps);
        u64 min_bytes;
        int ret;
 
@@ -2557,7 +2552,6 @@ int btrfs_find_space_cluster(struct btrfs_trans_handle *trans,
                goto out;
        }
 
-       INIT_LIST_HEAD(&bitmaps);
        ret = setup_cluster_no_bitmap(block_group, cluster, &bitmaps, offset,
                                      bytes, min_bytes);
        if (ret)
index 53dcbdf..f8962a9 100644 (file)
@@ -398,6 +398,8 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
        struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
        struct btrfs_path *path;
        struct inode *inode;
+       struct btrfs_block_rsv *rsv;
+       u64 num_bytes;
        u64 alloc_hint = 0;
        int ret;
        int prealloc;
@@ -421,11 +423,26 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
        if (!path)
                return -ENOMEM;
 
+       rsv = trans->block_rsv;
+       trans->block_rsv = &root->fs_info->trans_block_rsv;
+
+       num_bytes = trans->bytes_reserved;
+       /*
+        * 1 item for inode item insertion if need
+        * 3 items for inode item update (in the worst case)
+        * 1 item for free space object
+        * 3 items for pre-allocation
+        */
+       trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 8);
+       ret = btrfs_block_rsv_add_noflush(root, trans->block_rsv,
+                                         trans->bytes_reserved);
+       if (ret)
+               goto out;
 again:
        inode = lookup_free_ino_inode(root, path);
        if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
                ret = PTR_ERR(inode);
-               goto out;
+               goto out_release;
        }
 
        if (IS_ERR(inode)) {
@@ -434,7 +451,7 @@ again:
 
                ret = create_free_ino_inode(root, trans, path);
                if (ret)
-                       goto out;
+                       goto out_release;
                goto again;
        }
 
@@ -477,11 +494,14 @@ again:
        }
        btrfs_free_reserved_data_space(inode, prealloc);
 
+       ret = btrfs_write_out_ino_cache(root, trans, path);
 out_put:
        iput(inode);
+out_release:
+       btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
 out:
-       if (ret == 0)
-               ret = btrfs_write_out_ino_cache(root, trans, path);
+       trans->block_rsv = rsv;
+       trans->bytes_reserved = num_bytes;
 
        btrfs_free_path(path);
        return ret;
index 966ddcc..2c984f7 100644 (file)
@@ -93,6 +93,8 @@ static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
                                   u64 start, u64 end, int *page_started,
                                   unsigned long *nr_written, int unlock);
+static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode);
 
 static int btrfs_init_inode_security(struct btrfs_trans_handle *trans,
                                     struct inode *inode,  struct inode *dir,
@@ -1741,7 +1743,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
                                trans = btrfs_join_transaction(root);
                        BUG_ON(IS_ERR(trans));
                        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
-                       ret = btrfs_update_inode(trans, root, inode);
+                       ret = btrfs_update_inode_fallback(trans, root, inode);
                        BUG_ON(ret);
                }
                goto out;
@@ -1791,7 +1793,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
 
        ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
        if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
-               ret = btrfs_update_inode(trans, root, inode);
+               ret = btrfs_update_inode_fallback(trans, root, inode);
                BUG_ON(ret);
        }
        ret = 0;
@@ -2199,6 +2201,9 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                if (ret)
                        goto out;
        }
+       /* release the path since we're done with it */
+       btrfs_release_path(path);
+
        root->orphan_cleanup_state = ORPHAN_CLEANUP_DONE;
 
        if (root->orphan_block_rsv)
@@ -2426,7 +2431,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
 /*
  * copy everything in the in-memory inode into the btree.
  */
-noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
+static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root, struct inode *inode)
 {
        struct btrfs_inode_item *inode_item;
@@ -2434,21 +2439,6 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
        struct extent_buffer *leaf;
        int ret;
 
-       /*
-        * If the inode is a free space inode, we can deadlock during commit
-        * if we put it into the delayed code.
-        *
-        * The data relocation inode should also be directly updated
-        * without delay
-        */
-       if (!btrfs_is_free_space_inode(root, inode)
-           && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
-               ret = btrfs_delayed_update_inode(trans, root, inode);
-               if (!ret)
-                       btrfs_set_inode_last_trans(trans, inode);
-               return ret;
-       }
-
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -2476,6 +2466,43 @@ failed:
        return ret;
 }
 
+/*
+ * copy everything in the in-memory inode into the btree.
+ */
+noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode)
+{
+       int ret;
+
+       /*
+        * If the inode is a free space inode, we can deadlock during commit
+        * if we put it into the delayed code.
+        *
+        * The data relocation inode should also be directly updated
+        * without delay
+        */
+       if (!btrfs_is_free_space_inode(root, inode)
+           && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
+               ret = btrfs_delayed_update_inode(trans, root, inode);
+               if (!ret)
+                       btrfs_set_inode_last_trans(trans, inode);
+               return ret;
+       }
+
+       return btrfs_update_inode_item(trans, root, inode);
+}
+
+static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
+                               struct btrfs_root *root, struct inode *inode)
+{
+       int ret;
+
+       ret = btrfs_update_inode(trans, root, inode);
+       if (ret == -ENOSPC)
+               return btrfs_update_inode_item(trans, root, inode);
+       return ret;
+}
+
 /*
  * unlink helper that gets used here in inode.c and in the tree logging
  * recovery code.  It remove a link in a directory with a given name, and
@@ -3463,7 +3490,7 @@ void btrfs_evict_inode(struct inode *inode)
         * doing the truncate.
         */
        while (1) {
-               ret = btrfs_block_rsv_refill(root, rsv, min_size);
+               ret = btrfs_block_rsv_refill_noflush(root, rsv, min_size);
 
                /*
                 * Try and steal from the global reserve since we will
@@ -5632,7 +5659,7 @@ again:
        if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) {
                ret = btrfs_ordered_update_i_size(inode, 0, ordered);
                if (!ret)
-                       err = btrfs_update_inode(trans, root, inode);
+                       err = btrfs_update_inode_fallback(trans, root, inode);
                goto out;
        }
 
@@ -5670,7 +5697,7 @@ again:
        add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
        ret = btrfs_ordered_update_i_size(inode, 0, ordered);
        if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags))
-               btrfs_update_inode(trans, root, inode);
+               btrfs_update_inode_fallback(trans, root, inode);
        ret = 0;
 out_unlock:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset,
@@ -6529,14 +6556,16 @@ end_trans:
                ret = btrfs_orphan_del(NULL, inode);
        }
 
-       trans->block_rsv = &root->fs_info->trans_block_rsv;
-       ret = btrfs_update_inode(trans, root, inode);
-       if (ret && !err)
-               err = ret;
+       if (trans) {
+               trans->block_rsv = &root->fs_info->trans_block_rsv;
+               ret = btrfs_update_inode(trans, root, inode);
+               if (ret && !err)
+                       err = ret;
 
-       nr = trans->blocks_used;
-       ret = btrfs_end_transaction_throttle(trans, root);
-       btrfs_btree_balance_dirty(root, nr);
+               nr = trans->blocks_used;
+               ret = btrfs_end_transaction_throttle(trans, root);
+               btrfs_btree_balance_dirty(root, nr);
+       }
 
 out:
        btrfs_free_block_rsv(root, rsv);
@@ -6605,6 +6634,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        ei->orphan_meta_reserved = 0;
        ei->dummy_inode = 0;
        ei->in_defrag = 0;
+       ei->delalloc_meta_reserved = 0;
        ei->force_compress = BTRFS_COMPRESS_NONE;
 
        ei->delayed_node = NULL;
@@ -6764,11 +6794,13 @@ static int btrfs_getattr(struct vfsmount *mnt,
                         struct dentry *dentry, struct kstat *stat)
 {
        struct inode *inode = dentry->d_inode;
+       u32 blocksize = inode->i_sb->s_blocksize;
+
        generic_fillattr(inode, stat);
        stat->dev = BTRFS_I(inode)->root->anon_dev;
        stat->blksize = PAGE_CACHE_SIZE;
-       stat->blocks = (inode_get_bytes(inode) +
-                       BTRFS_I(inode)->delalloc_bytes) >> 9;
+       stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) +
+               ALIGN(BTRFS_I(inode)->delalloc_bytes, blocksize)) >> 9;
        return 0;
 }
 
index 4a34c47..72d4616 100644 (file)
@@ -1216,12 +1216,12 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
                *devstr = '\0';
                devstr = vol_args->name;
                devid = simple_strtoull(devstr, &end, 10);
-               printk(KERN_INFO "resizing devid %llu\n",
+               printk(KERN_INFO "btrfs: resizing devid %llu\n",
                       (unsigned long long)devid);
        }
        device = btrfs_find_device(root, devid, NULL, NULL);
        if (!device) {
-               printk(KERN_INFO "resizer unable to find device %llu\n",
+               printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",
                       (unsigned long long)devid);
                ret = -EINVAL;
                goto out_unlock;
@@ -1267,7 +1267,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
        do_div(new_size, root->sectorsize);
        new_size *= root->sectorsize;
 
-       printk(KERN_INFO "new size for %s is %llu\n",
+       printk(KERN_INFO "btrfs: new size for %s is %llu\n",
                device->name, (unsigned long long)new_size);
 
        if (new_size > old_size) {
@@ -1278,7 +1278,7 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
                }
                ret = btrfs_grow_device(trans, device, new_size);
                btrfs_commit_transaction(trans, root);
-       } else {
+       } else if (new_size < old_size) {
                ret = btrfs_shrink_device(device, new_size);
        }
 
@@ -2930,11 +2930,13 @@ static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
                goto out;
 
        for (i = 0; i < ipath->fspath->elem_cnt; ++i) {
-               rel_ptr = ipath->fspath->val[i] - (u64)ipath->fspath->val;
+               rel_ptr = ipath->fspath->val[i] -
+                         (u64)(unsigned long)ipath->fspath->val;
                ipath->fspath->val[i] = rel_ptr;
        }
 
-       ret = copy_to_user((void *)ipa->fspath, (void *)ipath->fspath, size);
+       ret = copy_to_user((void *)(unsigned long)ipa->fspath,
+                          (void *)(unsigned long)ipath->fspath, size);
        if (ret) {
                ret = -EFAULT;
                goto out;
@@ -3017,7 +3019,8 @@ static long btrfs_ioctl_logical_to_ino(struct btrfs_root *root,
        if (ret < 0)
                goto out;
 
-       ret = copy_to_user((void *)loi->inodes, (void *)inodes, size);
+       ret = copy_to_user((void *)(unsigned long)loi->inodes,
+                          (void *)(unsigned long)inodes, size);
        if (ret)
                ret = -EFAULT;
 
index 24d654c..dff29d5 100644 (file)
@@ -1174,6 +1174,8 @@ static int clone_backref_node(struct btrfs_trans_handle *trans,
                        list_add_tail(&new_edge->list[UPPER],
                                      &new_node->lower);
                }
+       } else {
+               list_add_tail(&new_node->lower, &cache->leaves);
        }
 
        rb_node = tree_insert(&cache->rb_root, new_node->bytenr,
index ed11d38..c27bcb6 100644 (file)
@@ -256,6 +256,11 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx)
        btrfs_release_path(swarn->path);
 
        ipath = init_ipath(4096, local_root, swarn->path);
+       if (IS_ERR(ipath)) {
+               ret = PTR_ERR(ipath);
+               ipath = NULL;
+               goto err;
+       }
        ret = paths_from_inode(inum, ipath);
 
        if (ret < 0)
@@ -272,7 +277,7 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx)
                        swarn->logical, swarn->dev->name,
                        (unsigned long long)swarn->sector, root, inum, offset,
                        min(isize - offset, (u64)PAGE_SIZE), nlink,
-                       (char *)ipath->fspath->val[i]);
+                       (char *)(unsigned long)ipath->fspath->val[i]);
 
        free_ipath(ipath);
        return 0;
@@ -944,50 +949,18 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer)
 static int scrub_submit(struct scrub_dev *sdev)
 {
        struct scrub_bio *sbio;
-       struct bio *bio;
-       int i;
 
        if (sdev->curr == -1)
                return 0;
 
        sbio = sdev->bios[sdev->curr];
-
-       bio = bio_alloc(GFP_NOFS, sbio->count);
-       if (!bio)
-               goto nomem;
-
-       bio->bi_private = sbio;
-       bio->bi_end_io = scrub_bio_end_io;
-       bio->bi_bdev = sdev->dev->bdev;
-       bio->bi_sector = sbio->physical >> 9;
-
-       for (i = 0; i < sbio->count; ++i) {
-               struct page *page;
-               int ret;
-
-               page = alloc_page(GFP_NOFS);
-               if (!page)
-                       goto nomem;
-
-               ret = bio_add_page(bio, page, PAGE_SIZE, 0);
-               if (!ret) {
-                       __free_page(page);
-                       goto nomem;
-               }
-       }
-
        sbio->err = 0;
        sdev->curr = -1;
        atomic_inc(&sdev->in_flight);
 
-       submit_bio(READ, bio);
+       submit_bio(READ, sbio->bio);
 
        return 0;
-
-nomem:
-       scrub_free_bio(bio);
-
-       return -ENOMEM;
 }
 
 static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len,
@@ -995,6 +968,8 @@ static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len,
                      u8 *csum, int force)
 {
        struct scrub_bio *sbio;
+       struct page *page;
+       int ret;
 
 again:
        /*
@@ -1015,12 +990,22 @@ again:
        }
        sbio = sdev->bios[sdev->curr];
        if (sbio->count == 0) {
+               struct bio *bio;
+
                sbio->physical = physical;
                sbio->logical = logical;
+               bio = bio_alloc(GFP_NOFS, SCRUB_PAGES_PER_BIO);
+               if (!bio)
+                       return -ENOMEM;
+
+               bio->bi_private = sbio;
+               bio->bi_end_io = scrub_bio_end_io;
+               bio->bi_bdev = sdev->dev->bdev;
+               bio->bi_sector = sbio->physical >> 9;
+               sbio->err = 0;
+               sbio->bio = bio;
        } else if (sbio->physical + sbio->count * PAGE_SIZE != physical ||
                   sbio->logical + sbio->count * PAGE_SIZE != logical) {
-               int ret;
-
                ret = scrub_submit(sdev);
                if (ret)
                        return ret;
@@ -1030,6 +1015,20 @@ again:
        sbio->spag[sbio->count].generation = gen;
        sbio->spag[sbio->count].have_csum = 0;
        sbio->spag[sbio->count].mirror_num = mirror_num;
+
+       page = alloc_page(GFP_NOFS);
+       if (!page)
+               return -ENOMEM;
+
+       ret = bio_add_page(sbio->bio, page, PAGE_SIZE, 0);
+       if (!ret) {
+               __free_page(page);
+               ret = scrub_submit(sdev);
+               if (ret)
+                       return ret;
+               goto again;
+       }
+
        if (csum) {
                sbio->spag[sbio->count].have_csum = 1;
                memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size);
index 57080df..e28ad4b 100644 (file)
@@ -197,7 +197,7 @@ static match_table_t tokens = {
        {Opt_subvolrootid, "subvolrootid=%d"},
        {Opt_defrag, "autodefrag"},
        {Opt_inode_cache, "inode_cache"},
-       {Opt_no_space_cache, "no_space_cache"},
+       {Opt_no_space_cache, "nospace_cache"},
        {Opt_recovery, "recovery"},
        {Opt_err, NULL},
 };
@@ -448,6 +448,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
                token = match_token(p, tokens, args);
                switch (token) {
                case Opt_subvol:
+                       kfree(*subvol_name);
                        *subvol_name = match_strdup(&args[0]);
                        break;
                case Opt_subvolid:
@@ -710,7 +711,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
        if (btrfs_test_opt(root, SPACE_CACHE))
                seq_puts(seq, ",space_cache");
        else
-               seq_puts(seq, ",no_space_cache");
+               seq_puts(seq, ",nospace_cache");
        if (btrfs_test_opt(root, CLEAR_CACHE))
                seq_puts(seq, ",clear_cache");
        if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED))
@@ -824,13 +825,9 @@ static char *setup_root_args(char *args)
 static struct dentry *mount_subvol(const char *subvol_name, int flags,
                                   const char *device_name, char *data)
 {
-       struct super_block *s;
        struct dentry *root;
        struct vfsmount *mnt;
-       struct mnt_namespace *ns_private;
        char *newargs;
-       struct path path;
-       int error;
 
        newargs = setup_root_args(data);
        if (!newargs)
@@ -841,39 +838,17 @@ static struct dentry *mount_subvol(const char *subvol_name, int flags,
        if (IS_ERR(mnt))
                return ERR_CAST(mnt);
 
-       ns_private = create_mnt_ns(mnt);
-       if (IS_ERR(ns_private)) {
-               mntput(mnt);
-               return ERR_CAST(ns_private);
-       }
-
-       /*
-        * This will trigger the automount of the subvol so we can just
-        * drop the mnt we have here and return the dentry that we
-        * found.
-        */
-       error = vfs_path_lookup(mnt->mnt_root, mnt, subvol_name,
-                               LOOKUP_FOLLOW, &path);
-       put_mnt_ns(ns_private);
-       if (error)
-               return ERR_PTR(error);
+       root = mount_subtree(mnt, subvol_name);
 
-       if (!is_subvolume_inode(path.dentry->d_inode)) {
-               path_put(&path);
-               mntput(mnt);
-               error = -EINVAL;
+       if (!IS_ERR(root) && !is_subvolume_inode(root->d_inode)) {
+               struct super_block *s = root->d_sb;
+               dput(root);
+               root = ERR_PTR(-EINVAL);
+               deactivate_locked_super(s);
                printk(KERN_ERR "btrfs: '%s' is not a valid subvolume\n",
                                subvol_name);
-               return ERR_PTR(-EINVAL);
        }
 
-       /* Get a ref to the sb and the dentry we found and return it */
-       s = path.mnt->mnt_sb;
-       atomic_inc(&s->s_active);
-       root = dget(path.dentry);
-       path_put(&path);
-       down_write(&s->s_umount);
-
        return root;
 }
 
@@ -890,7 +865,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        struct super_block *s;
        struct dentry *root;
        struct btrfs_fs_devices *fs_devices = NULL;
-       struct btrfs_root *tree_root = NULL;
        struct btrfs_fs_info *fs_info = NULL;
        fmode_t mode = FMODE_READ;
        char *subvol_name = NULL;
@@ -904,8 +878,10 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        error = btrfs_parse_early_options(data, mode, fs_type,
                                          &subvol_name, &subvol_objectid,
                                          &subvol_rootid, &fs_devices);
-       if (error)
+       if (error) {
+               kfree(subvol_name);
                return ERR_PTR(error);
+       }
 
        if (subvol_name) {
                root = mount_subvol(subvol_name, flags, device_name, data);
@@ -917,15 +893,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        if (error)
                return ERR_PTR(error);
 
-       error = btrfs_open_devices(fs_devices, mode, fs_type);
-       if (error)
-               return ERR_PTR(error);
-
-       if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
-               error = -EACCES;
-               goto error_close_devices;
-       }
-
        /*
         * Setup a dummy root and fs_info for test/set super.  This is because
         * we don't actually fill this stuff out until open_ctree, but we need
@@ -933,24 +900,36 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
         * then open_ctree will properly initialize everything later.
         */
        fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS);
-       tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
-       if (!fs_info || !tree_root) {
+       if (!fs_info)
+               return ERR_PTR(-ENOMEM);
+
+       fs_info->tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS);
+       if (!fs_info->tree_root) {
                error = -ENOMEM;
-               goto error_close_devices;
+               goto error_fs_info;
        }
-       fs_info->tree_root = tree_root;
+       fs_info->tree_root->fs_info = fs_info;
        fs_info->fs_devices = fs_devices;
-       tree_root->fs_info = fs_info;
 
        fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
        fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS);
        if (!fs_info->super_copy || !fs_info->super_for_commit) {
                error = -ENOMEM;
+               goto error_fs_info;
+       }
+
+       error = btrfs_open_devices(fs_devices, mode, fs_type);
+       if (error)
+               goto error_fs_info;
+
+       if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) {
+               error = -EACCES;
                goto error_close_devices;
        }
 
        bdev = fs_devices->latest_bdev;
-       s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root);
+       s = sget(fs_type, btrfs_test_super, btrfs_set_super,
+                fs_info->tree_root);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto error_close_devices;
@@ -959,12 +938,12 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        if (s->s_root) {
                if ((flags ^ s->s_flags) & MS_RDONLY) {
                        deactivate_locked_super(s);
-                       return ERR_PTR(-EBUSY);
+                       error = -EBUSY;
+                       goto error_close_devices;
                }
 
                btrfs_close_devices(fs_devices);
                free_fs_info(fs_info);
-               kfree(tree_root);
        } else {
                char b[BDEVNAME_SIZE];
 
@@ -991,8 +970,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
 
 error_close_devices:
        btrfs_close_devices(fs_devices);
+error_fs_info:
        free_fs_info(fs_info);
-       kfree(tree_root);
        return ERR_PTR(error);
 }
 
@@ -1078,7 +1057,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
        int i = 0, nr_devices;
        int ret;
 
-       nr_devices = fs_info->fs_devices->rw_devices;
+       nr_devices = fs_info->fs_devices->open_devices;
        BUG_ON(!nr_devices);
 
        devices_info = kmalloc(sizeof(*devices_info) * nr_devices,
@@ -1100,8 +1079,8 @@ static int btrfs_calc_avail_data_space(struct btrfs_root *root, u64 *free_bytes)
        else
                min_stripe_size = BTRFS_STRIPE_LEN;
 
-       list_for_each_entry(device, &fs_devices->alloc_list, dev_alloc_list) {
-               if (!device->in_fs_metadata)
+       list_for_each_entry(device, &fs_devices->devices, dev_list) {
+               if (!device->in_fs_metadata || !device->bdev)
                        continue;
 
                avail_space = device->total_bytes - device->bytes_used;
index 960835e..81376d9 100644 (file)
@@ -785,6 +785,10 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
 
                        btrfs_save_ino_cache(root, trans);
 
+                       /* see comments in should_cow_block() */
+                       root->force_cow = 0;
+                       smp_wmb();
+
                        if (root->commit_root != root->node) {
                                mutex_lock(&root->fs_commit_mutex);
                                switch_commit_root(root);
@@ -882,8 +886,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_reloc_pre_snapshot(trans, pending, &to_reserve);
 
        if (to_reserve > 0) {
-               ret = btrfs_block_rsv_add(root, &pending->block_rsv,
-                                         to_reserve);
+               ret = btrfs_block_rsv_add_noflush(root, &pending->block_rsv,
+                                                 to_reserve);
                if (ret) {
                        pending->error = ret;
                        goto fail;
@@ -947,6 +951,10 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        btrfs_tree_unlock(old);
        free_extent_buffer(old);
 
+       /* see comments in should_cow_block() */
+       root->force_cow = 1;
+       smp_wmb();
+
        btrfs_set_root_node(new_root_item, tmp);
        /* record when the snapshot was created in key.offset */
        key.offset = trans->transid;
index f8e2943..c37433d 100644 (file)
@@ -999,7 +999,7 @@ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
        key.objectid = device->devid;
        key.offset = start;
        key.type = BTRFS_DEV_EXTENT_KEY;
-
+again:
        ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
        if (ret > 0) {
                ret = btrfs_previous_item(root, path, key.objectid,
@@ -1012,6 +1012,9 @@ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans,
                                        struct btrfs_dev_extent);
                BUG_ON(found_key.offset > start || found_key.offset +
                       btrfs_dev_extent_length(leaf, extent) < start);
+               key = found_key;
+               btrfs_release_path(path);
+               goto again;
        } else if (ret == 0) {
                leaf = path->nodes[0];
                extent = btrfs_item_ptr(leaf, path->slots[0],
index ab5b1c4..78f2d4d 100644 (file)
@@ -100,6 +100,12 @@ struct btrfs_device {
        struct reada_zone *reada_curr_zone;
        struct radix_tree_root reada_zones;
        struct radix_tree_root reada_extents;
+
+       /* for sending down flush barriers */
+       struct bio *flush_bio;
+       struct completion flush_wait;
+       int nobarriers;
+
 };
 
 struct btrfs_fs_devices {
index 2abd0df..bca3948 100644 (file)
@@ -1143,7 +1143,7 @@ static void ceph_d_prune(struct dentry *dentry)
 {
        struct ceph_dentry_info *di;
 
-       dout("d_release %p\n", dentry);
+       dout("ceph_d_prune %p\n", dentry);
 
        /* do we have a valid parent? */
        if (!dentry->d_parent || IS_ROOT(dentry))
index e392bfc..116f365 100644 (file)
@@ -1328,12 +1328,13 @@ int ceph_inode_set_size(struct inode *inode, loff_t size)
  */
 void ceph_queue_writeback(struct inode *inode)
 {
+       ihold(inode);
        if (queue_work(ceph_inode_to_client(inode)->wb_wq,
                       &ceph_inode(inode)->i_wb_work)) {
                dout("ceph_queue_writeback %p\n", inode);
-               ihold(inode);
        } else {
                dout("ceph_queue_writeback %p failed\n", inode);
+               iput(inode);
        }
 }
 
@@ -1353,12 +1354,13 @@ static void ceph_writeback_work(struct work_struct *work)
  */
 void ceph_queue_invalidate(struct inode *inode)
 {
+       ihold(inode);
        if (queue_work(ceph_inode_to_client(inode)->pg_inv_wq,
                       &ceph_inode(inode)->i_pg_inv_work)) {
                dout("ceph_queue_invalidate %p\n", inode);
-               ihold(inode);
        } else {
                dout("ceph_queue_invalidate %p failed\n", inode);
+               iput(inode);
        }
 }
 
@@ -1434,13 +1436,14 @@ void ceph_queue_vmtruncate(struct inode *inode)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
 
+       ihold(inode);
        if (queue_work(ceph_sb_to_client(inode->i_sb)->trunc_wq,
                       &ci->i_vmtruncate_work)) {
                dout("ceph_queue_vmtruncate %p\n", inode);
-               ihold(inode);
        } else {
                dout("ceph_queue_vmtruncate %p failed, pending=%d\n",
                     inode, ci->i_truncate_pending);
+               iput(inode);
        }
 }
 
index a90846f..8dc73a5 100644 (file)
@@ -638,10 +638,12 @@ static struct dentry *open_root_dentry(struct ceph_fs_client *fsc,
        if (err == 0) {
                dout("open_root_inode success\n");
                if (ceph_ino(req->r_target_inode) == CEPH_INO_ROOT &&
-                   fsc->sb->s_root == NULL)
+                   fsc->sb->s_root == NULL) {
                        root = d_alloc_root(req->r_target_inode);
-               else
+                       ceph_init_dentry(root);
+               } else {
                        root = d_obtain_alias(req->r_target_inode);
+               }
                req->r_target_inode = NULL;
                dout("open_root_inode success, root dentry is %p\n", root);
        } else {
index a901c69..10ba92d 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/bit_spinlock.h>
 #include <linux/rculist_bl.h>
 #include <linux/prefetch.h>
+#include <linux/ratelimit.h>
 #include "internal.h"
 
 /*
@@ -2383,8 +2384,16 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
                                actual = __d_unalias(inode, dentry, alias);
                        }
                        write_sequnlock(&rename_lock);
-                       if (IS_ERR(actual))
+                       if (IS_ERR(actual)) {
+                               if (PTR_ERR(actual) == -ELOOP)
+                                       pr_warn_ratelimited(
+                                               "VFS: Lookup of '%s' in %s %s"
+                                               " would have caused loop\n",
+                                               dentry->d_name.name,
+                                               inode->i_sb->s_type->name,
+                                               inode->i_sb->s_id);
                                dput(alias);
+                       }
                        goto out_nolock;
                }
        }
index 58609bd..2a83425 100644 (file)
@@ -967,7 +967,7 @@ static void ecryptfs_set_default_crypt_stat_vals(
 
 /**
  * ecryptfs_new_file_context
- * @ecryptfs_dentry: The eCryptfs dentry
+ * @ecryptfs_inode: The eCryptfs inode
  *
  * If the crypto context for the file has not yet been established,
  * this is where we do that.  Establishing a new crypto context
@@ -984,13 +984,13 @@ static void ecryptfs_set_default_crypt_stat_vals(
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry)
+int ecryptfs_new_file_context(struct inode *ecryptfs_inode)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
-           &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+           &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        struct ecryptfs_mount_crypt_stat *mount_crypt_stat =
            &ecryptfs_superblock_to_private(
-                   ecryptfs_dentry->d_sb)->mount_crypt_stat;
+                   ecryptfs_inode->i_sb)->mount_crypt_stat;
        int cipher_name_len;
        int rc = 0;
 
@@ -1299,12 +1299,12 @@ static int ecryptfs_write_headers_virt(char *page_virt, size_t max,
 }
 
 static int
-ecryptfs_write_metadata_to_contents(struct dentry *ecryptfs_dentry,
+ecryptfs_write_metadata_to_contents(struct inode *ecryptfs_inode,
                                    char *virt, size_t virt_len)
 {
        int rc;
 
-       rc = ecryptfs_write_lower(ecryptfs_dentry->d_inode, virt,
+       rc = ecryptfs_write_lower(ecryptfs_inode, virt,
                                  0, virt_len);
        if (rc < 0)
                printk(KERN_ERR "%s: Error attempting to write header "
@@ -1338,7 +1338,8 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask,
 
 /**
  * ecryptfs_write_metadata
- * @ecryptfs_dentry: The eCryptfs dentry
+ * @ecryptfs_dentry: The eCryptfs dentry, which should be negative
+ * @ecryptfs_inode: The newly created eCryptfs inode
  *
  * Write the file headers out.  This will likely involve a userspace
  * callout, in which the session key is encrypted with one or more
@@ -1348,10 +1349,11 @@ static unsigned long ecryptfs_get_zeroed_pages(gfp_t gfp_mask,
  *
  * Returns zero on success; non-zero on error
  */
-int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+                           struct inode *ecryptfs_inode)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
-               &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+               &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        unsigned int order;
        char *virt;
        size_t virt_len;
@@ -1391,7 +1393,7 @@ int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry)
                rc = ecryptfs_write_metadata_to_xattr(ecryptfs_dentry, virt,
                                                      size);
        else
-               rc = ecryptfs_write_metadata_to_contents(ecryptfs_dentry, virt,
+               rc = ecryptfs_write_metadata_to_contents(ecryptfs_inode, virt,
                                                         virt_len);
        if (rc) {
                printk(KERN_ERR "%s: Error writing metadata out to lower file; "
@@ -1943,7 +1945,7 @@ static unsigned char *portable_filename_chars = ("-.0123456789ABCD"
 
 /* We could either offset on every reverse map or just pad some 0x00's
  * at the front here */
-static const unsigned char filename_rev_map[] = {
+static const unsigned char filename_rev_map[256] = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 15 */
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 23 */
@@ -1959,7 +1961,7 @@ static const unsigned char filename_rev_map[] = {
        0x00, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, /* 103 */
        0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, /* 111 */
        0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, /* 119 */
-       0x3D, 0x3E, 0x3F
+       0x3D, 0x3E, 0x3F /* 123 - 255 initialized to 0x00 */
 };
 
 /**
index 54481a3..a9f29b1 100644 (file)
@@ -584,9 +584,10 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat);
 int ecryptfs_write_inode_size_to_metadata(struct inode *ecryptfs_inode);
 int ecryptfs_encrypt_page(struct page *page);
 int ecryptfs_decrypt_page(struct page *page);
-int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry);
+int ecryptfs_write_metadata(struct dentry *ecryptfs_dentry,
+                           struct inode *ecryptfs_inode);
 int ecryptfs_read_metadata(struct dentry *ecryptfs_dentry);
-int ecryptfs_new_file_context(struct dentry *ecryptfs_dentry);
+int ecryptfs_new_file_context(struct inode *ecryptfs_inode);
 void ecryptfs_write_crypt_stat_flags(char *page_virt,
                                     struct ecryptfs_crypt_stat *crypt_stat,
                                     size_t *written);
index c6ac98c..d3f95f9 100644 (file)
@@ -139,6 +139,27 @@ out:
        return rc;
 }
 
+static void ecryptfs_vma_close(struct vm_area_struct *vma)
+{
+       filemap_write_and_wait(vma->vm_file->f_mapping);
+}
+
+static const struct vm_operations_struct ecryptfs_file_vm_ops = {
+       .close          = ecryptfs_vma_close,
+       .fault          = filemap_fault,
+};
+
+static int ecryptfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       int rc;
+
+       rc = generic_file_mmap(file, vma);
+       if (!rc)
+               vma->vm_ops = &ecryptfs_file_vm_ops;
+
+       return rc;
+}
+
 struct kmem_cache *ecryptfs_file_info_cache;
 
 /**
@@ -349,7 +370,7 @@ const struct file_operations ecryptfs_main_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl = ecryptfs_compat_ioctl,
 #endif
-       .mmap = generic_file_mmap,
+       .mmap = ecryptfs_file_mmap,
        .open = ecryptfs_open,
        .flush = ecryptfs_flush,
        .release = ecryptfs_release,
index a36d327..32f90a3 100644 (file)
@@ -172,22 +172,23 @@ ecryptfs_create_underlying_file(struct inode *lower_dir_inode,
  * it. It will also update the eCryptfs directory inode to mimic the
  * stat of the lower directory inode.
  *
- * Returns zero on success; non-zero on error condition
+ * Returns the new eCryptfs inode on success; an ERR_PTR on error condition
  */
-static int
+static struct inode *
 ecryptfs_do_create(struct inode *directory_inode,
                   struct dentry *ecryptfs_dentry, int mode)
 {
        int rc;
        struct dentry *lower_dentry;
        struct dentry *lower_dir_dentry;
+       struct inode *inode;
 
        lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
        lower_dir_dentry = lock_parent(lower_dentry);
        if (IS_ERR(lower_dir_dentry)) {
                ecryptfs_printk(KERN_ERR, "Error locking directory of "
                                "dentry\n");
-               rc = PTR_ERR(lower_dir_dentry);
+               inode = ERR_CAST(lower_dir_dentry);
                goto out;
        }
        rc = ecryptfs_create_underlying_file(lower_dir_dentry->d_inode,
@@ -195,20 +196,19 @@ ecryptfs_do_create(struct inode *directory_inode,
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
                       "rc = [%d]\n", __func__, rc);
+               inode = ERR_PTR(rc);
                goto out_lock;
        }
-       rc = ecryptfs_interpose(lower_dentry, ecryptfs_dentry,
-                               directory_inode->i_sb);
-       if (rc) {
-               ecryptfs_printk(KERN_ERR, "Failure in ecryptfs_interpose\n");
+       inode = __ecryptfs_get_inode(lower_dentry->d_inode,
+                                    directory_inode->i_sb);
+       if (IS_ERR(inode))
                goto out_lock;
-       }
        fsstack_copy_attr_times(directory_inode, lower_dir_dentry->d_inode);
        fsstack_copy_inode_size(directory_inode, lower_dir_dentry->d_inode);
 out_lock:
        unlock_dir(lower_dir_dentry);
 out:
-       return rc;
+       return inode;
 }
 
 /**
@@ -219,26 +219,26 @@ out:
  *
  * Returns zero on success
  */
-static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
+static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry,
+                                   struct inode *ecryptfs_inode)
 {
        struct ecryptfs_crypt_stat *crypt_stat =
-               &ecryptfs_inode_to_private(ecryptfs_dentry->d_inode)->crypt_stat;
+               &ecryptfs_inode_to_private(ecryptfs_inode)->crypt_stat;
        int rc = 0;
 
-       if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) {
+       if (S_ISDIR(ecryptfs_inode->i_mode)) {
                ecryptfs_printk(KERN_DEBUG, "This is a directory\n");
                crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
                goto out;
        }
        ecryptfs_printk(KERN_DEBUG, "Initializing crypto context\n");
-       rc = ecryptfs_new_file_context(ecryptfs_dentry);
+       rc = ecryptfs_new_file_context(ecryptfs_inode);
        if (rc) {
                ecryptfs_printk(KERN_ERR, "Error creating new file "
                                "context; rc = [%d]\n", rc);
                goto out;
        }
-       rc = ecryptfs_get_lower_file(ecryptfs_dentry,
-                                    ecryptfs_dentry->d_inode);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry, ecryptfs_inode);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
                        "the lower file for the dentry with name "
@@ -246,10 +246,10 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                        ecryptfs_dentry->d_name.name, rc);
                goto out;
        }
-       rc = ecryptfs_write_metadata(ecryptfs_dentry);
+       rc = ecryptfs_write_metadata(ecryptfs_dentry, ecryptfs_inode);
        if (rc)
                printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
-       ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
+       ecryptfs_put_lower_file(ecryptfs_inode);
 out:
        return rc;
 }
@@ -269,18 +269,28 @@ static int
 ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
                int mode, struct nameidata *nd)
 {
+       struct inode *ecryptfs_inode;
        int rc;
 
-       /* ecryptfs_do_create() calls ecryptfs_interpose() */
-       rc = ecryptfs_do_create(directory_inode, ecryptfs_dentry, mode);
-       if (unlikely(rc)) {
+       ecryptfs_inode = ecryptfs_do_create(directory_inode, ecryptfs_dentry,
+                                           mode);
+       if (unlikely(IS_ERR(ecryptfs_inode))) {
                ecryptfs_printk(KERN_WARNING, "Failed to create file in"
                                "lower filesystem\n");
+               rc = PTR_ERR(ecryptfs_inode);
                goto out;
        }
        /* At this point, a file exists on "disk"; we need to make sure
         * that this on disk file is prepared to be an ecryptfs file */
-       rc = ecryptfs_initialize_file(ecryptfs_dentry);
+       rc = ecryptfs_initialize_file(ecryptfs_dentry, ecryptfs_inode);
+       if (rc) {
+               drop_nlink(ecryptfs_inode);
+               unlock_new_inode(ecryptfs_inode);
+               iput(ecryptfs_inode);
+               goto out;
+       }
+       d_instantiate(ecryptfs_dentry, ecryptfs_inode);
+       unlock_new_inode(ecryptfs_inode);
 out:
        return rc;
 }
index f6dba45..12ccacd 100644 (file)
@@ -565,7 +565,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb)
        brelse(bitmap_bh);
        printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu"
               ", computed = %llu, %llu\n",
-              EXT4_B2C(sbi, ext4_free_blocks_count(es)),
+              EXT4_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)),
               desc_count, bitmap_count);
        return bitmap_count;
 #else
index 240f6e2..848f436 100644 (file)
@@ -2270,6 +2270,7 @@ retry:
                        ext4_msg(inode->i_sb, KERN_CRIT, "%s: jbd2_start: "
                               "%ld pages, ino %lu; err %d", __func__,
                                wbc->nr_to_write, inode->i_ino, ret);
+                       blk_finish_plug(&plug);
                        goto out_writepages;
                }
 
@@ -2806,8 +2807,8 @@ out:
        spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
 
        /* queue the work to convert unwritten extents to written */
-       queue_work(wq, &io_end->work);
        iocb->private = NULL;
+       queue_work(wq, &io_end->work);
 
        /* XXX: probably should move into the real I/O completion handler */
        inode_dio_done(inode);
index 9953d80..3858767 100644 (file)
@@ -1683,7 +1683,9 @@ static int parse_options(char *options, struct super_block *sb,
                        data_opt = EXT4_MOUNT_WRITEBACK_DATA;
                datacheck:
                        if (is_remount) {
-                               if (test_opt(sb, DATA_FLAGS) != data_opt) {
+                               if (!sbi->s_journal)
+                                       ext4_msg(sb, KERN_WARNING, "Remounting file system with no journal so ignoring journalled data option");
+                               else if (test_opt(sb, DATA_FLAGS) != data_opt) {
                                        ext4_msg(sb, KERN_ERR,
                                                "Cannot change data mode on remount");
                                        return 0;
@@ -3099,8 +3101,6 @@ static void ext4_destroy_lazyinit_thread(void)
 }
 
 static int ext4_fill_super(struct super_block *sb, void *data, int silent)
-                               __releases(kernel_lock)
-                               __acquires(kernel_lock)
 {
        char *orig_data = kstrdup(data, GFP_KERNEL);
        struct buffer_head *bh;
index e673a88..b1ce4c7 100644 (file)
@@ -40,6 +40,8 @@ int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in)
 
        src = in->name;
        srclen = in->len;
+       if (srclen > HFS_NAMELEN)
+               srclen = HFS_NAMELEN;
        dst = out;
        dstlen = HFS_MAX_NAMELEN;
        if (nls_io) {
index 3f32bcb..ef175cb 100644 (file)
 #include <linux/bitops.h>
 #include <linux/sched.h>
 
-static const int nibblemap[] = { 4,3,3,2,3,2,2,1,3,2,2,1,2,1,1,0 };
-
 static DEFINE_SPINLOCK(bitmap_lock);
 
-static unsigned long count_free(struct buffer_head *map[], unsigned numblocks, __u32 numbits)
+/*
+ * bitmap consists of blocks filled with 16bit words
+ * bit set == busy, bit clear == free
+ * endianness is a mess, but for counting zero bits it really doesn't matter...
+ */
+static __u32 count_free(struct buffer_head *map[], unsigned blocksize, __u32 numbits)
 {
-       unsigned i, j, sum = 0;
-       struct buffer_head *bh;
-  
-       for (i=0; i<numblocks-1; i++) {
-               if (!(bh=map[i])) 
-                       return(0);
-               for (j=0; j<bh->b_size; j++)
-                       sum += nibblemap[bh->b_data[j] & 0xf]
-                               + nibblemap[(bh->b_data[j]>>4) & 0xf];
-       }
+       __u32 sum = 0;
+       unsigned blocks = DIV_ROUND_UP(numbits, blocksize * 8);
 
-       if (numblocks==0 || !(bh=map[numblocks-1]))
-               return(0);
-       i = ((numbits - (numblocks-1) * bh->b_size * 8) / 16) * 2;
-       for (j=0; j<i; j++) {
-               sum += nibblemap[bh->b_data[j] & 0xf]
-                       + nibblemap[(bh->b_data[j]>>4) & 0xf];
+       while (blocks--) {
+               unsigned words = blocksize / 2;
+               __u16 *p = (__u16 *)(*map++)->b_data;
+               while (words--)
+                       sum += 16 - hweight16(*p++);
        }
 
-       i = numbits%16;
-       if (i!=0) {
-               i = *(__u16 *)(&bh->b_data[j]) | ~((1<<i) - 1);
-               sum += nibblemap[i & 0xf] + nibblemap[(i>>4) & 0xf];
-               sum += nibblemap[(i>>8) & 0xf] + nibblemap[(i>>12) & 0xf];
-       }
-       return(sum);
+       return sum;
 }
 
 void minix_free_block(struct inode *inode, unsigned long block)
@@ -105,10 +93,12 @@ int minix_new_block(struct inode * inode)
        return 0;
 }
 
-unsigned long minix_count_free_blocks(struct minix_sb_info *sbi)
+unsigned long minix_count_free_blocks(struct super_block *sb)
 {
-       return (count_free(sbi->s_zmap, sbi->s_zmap_blocks,
-               sbi->s_nzones - sbi->s_firstdatazone + 1)
+       struct minix_sb_info *sbi = minix_sb(sb);
+       u32 bits = sbi->s_nzones - (sbi->s_firstdatazone + 1);
+
+       return (count_free(sbi->s_zmap, sb->s_blocksize, bits)
                << sbi->s_log_zone_size);
 }
 
@@ -273,7 +263,10 @@ struct inode *minix_new_inode(const struct inode *dir, int mode, int *error)
        return inode;
 }
 
-unsigned long minix_count_free_inodes(struct minix_sb_info *sbi)
+unsigned long minix_count_free_inodes(struct super_block *sb)
 {
-       return count_free(sbi->s_imap, sbi->s_imap_blocks, sbi->s_ninodes + 1);
+       struct minix_sb_info *sbi = minix_sb(sb);
+       u32 bits = sbi->s_ninodes + 1;
+
+       return count_free(sbi->s_imap, sb->s_blocksize, bits);
 }
index 64cdcd6..1d9e339 100644 (file)
@@ -279,6 +279,27 @@ static int minix_fill_super(struct super_block *s, void *data, int silent)
        else if (sbi->s_mount_state & MINIX_ERROR_FS)
                printk("MINIX-fs: mounting file system with errors, "
                        "running fsck is recommended\n");
+
+       /* Apparently minix can create filesystems that allocate more blocks for
+        * the bitmaps than needed.  We simply ignore that, but verify it didn't
+        * create one with not enough blocks and bail out if so.
+        */
+       block = minix_blocks_needed(sbi->s_ninodes, s->s_blocksize);
+       if (sbi->s_imap_blocks < block) {
+               printk("MINIX-fs: file system does not have enough "
+                               "imap blocks allocated.  Refusing to mount\n");
+               goto out_iput;
+       }
+
+       block = minix_blocks_needed(
+                       (sbi->s_nzones - (sbi->s_firstdatazone + 1)),
+                       s->s_blocksize);
+       if (sbi->s_zmap_blocks < block) {
+               printk("MINIX-fs: file system does not have enough "
+                               "zmap blocks allocated.  Refusing to mount.\n");
+               goto out_iput;
+       }
+
        return 0;
 
 out_iput:
@@ -339,10 +360,10 @@ static int minix_statfs(struct dentry *dentry, struct kstatfs *buf)
        buf->f_type = sb->s_magic;
        buf->f_bsize = sb->s_blocksize;
        buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size;
-       buf->f_bfree = minix_count_free_blocks(sbi);
+       buf->f_bfree = minix_count_free_blocks(sb);
        buf->f_bavail = buf->f_bfree;
        buf->f_files = sbi->s_ninodes;
-       buf->f_ffree = minix_count_free_inodes(sbi);
+       buf->f_ffree = minix_count_free_inodes(sb);
        buf->f_namelen = sbi->s_namelen;
        buf->f_fsid.val[0] = (u32)id;
        buf->f_fsid.val[1] = (u32)(id >> 32);
index 341e212..26bbd55 100644 (file)
@@ -48,10 +48,10 @@ extern struct minix_inode * minix_V1_raw_inode(struct super_block *, ino_t, stru
 extern struct minix2_inode * minix_V2_raw_inode(struct super_block *, ino_t, struct buffer_head **);
 extern struct inode * minix_new_inode(const struct inode *, int, int *);
 extern void minix_free_inode(struct inode * inode);
-extern unsigned long minix_count_free_inodes(struct minix_sb_info *sbi);
+extern unsigned long minix_count_free_inodes(struct super_block *sb);
 extern int minix_new_block(struct inode * inode);
 extern void minix_free_block(struct inode *inode, unsigned long block);
-extern unsigned long minix_count_free_blocks(struct minix_sb_info *sbi);
+extern unsigned long minix_count_free_blocks(struct super_block *sb);
 extern int minix_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int minix_prepare_chunk(struct page *page, loff_t pos, unsigned len);
 
@@ -88,6 +88,11 @@ static inline struct minix_inode_info *minix_i(struct inode *inode)
        return list_entry(inode, struct minix_inode_info, vfs_inode);
 }
 
+static inline unsigned minix_blocks_needed(unsigned bits, unsigned blocksize)
+{
+       return DIV_ROUND_UP(bits, blocksize * 8);
+}
+
 #if defined(CONFIG_MINIX_FS_NATIVE_ENDIAN) && \
        defined(CONFIG_MINIX_FS_BIG_ENDIAN_16BIT_INDEXED)
 
@@ -125,7 +130,7 @@ static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)
        if (!size)
                return 0;
 
-       size = (size >> 4) + ((size & 15) > 0);
+       size >>= 4;
        while (*p++ == 0xffff) {
                if (--size == 0)
                        return (p - addr) << 4;
index e5e1c7d..6d3a196 100644 (file)
@@ -2483,11 +2483,43 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt)
                __mnt_make_longterm(mnt);
                new_ns->root = mnt;
                list_add(&new_ns->list, &new_ns->root->mnt_list);
+       } else {
+               mntput(mnt);
        }
        return new_ns;
 }
 EXPORT_SYMBOL(create_mnt_ns);
 
+struct dentry *mount_subtree(struct vfsmount *mnt, const char *name)
+{
+       struct mnt_namespace *ns;
+       struct super_block *s;
+       struct path path;
+       int err;
+
+       ns = create_mnt_ns(mnt);
+       if (IS_ERR(ns))
+               return ERR_CAST(ns);
+
+       err = vfs_path_lookup(mnt->mnt_root, mnt,
+                       name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
+
+       put_mnt_ns(ns);
+
+       if (err)
+               return ERR_PTR(err);
+
+       /* trade a vfsmount reference for active sb one */
+       s = path.mnt->mnt_sb;
+       atomic_inc(&s->s_active);
+       mntput(path.mnt);
+       /* lock the sucker */
+       down_write(&s->s_umount);
+       /* ... and return the root of (sub)tree on it */
+       return path.dentry;
+}
+EXPORT_SYMBOL(mount_subtree);
+
 SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
                char __user *, type, unsigned long, flags, void __user *, data)
 {
index b238d95..ac28990 100644 (file)
@@ -1468,12 +1468,12 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
                                res = NULL;
                                goto out;
                        /* This turned out not to be a regular file */
+                       case -EISDIR:
                        case -ENOTDIR:
                                goto no_open;
                        case -ELOOP:
                                if (!(nd->intent.open.flags & O_NOFOLLOW))
                                        goto no_open;
-                       /* case -EISDIR: */
                        /* case -EINVAL: */
                        default:
                                res = ERR_CAST(inode);
index 0a1f831..eca56d4 100644 (file)
 
 #define NFSDBG_FACILITY                NFSDBG_FILE
 
-static int nfs_file_open(struct inode *, struct file *);
-static int nfs_file_release(struct inode *, struct file *);
-static loff_t nfs_file_llseek(struct file *file, loff_t offset, int origin);
-static int  nfs_file_mmap(struct file *, struct vm_area_struct *);
-static ssize_t nfs_file_splice_read(struct file *filp, loff_t *ppos,
-                                       struct pipe_inode_info *pipe,
-                                       size_t count, unsigned int flags);
-static ssize_t nfs_file_read(struct kiocb *, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t pos);
-static ssize_t nfs_file_splice_write(struct pipe_inode_info *pipe,
-                                       struct file *filp, loff_t *ppos,
-                                       size_t count, unsigned int flags);
-static ssize_t nfs_file_write(struct kiocb *, const struct iovec *iov,
-                               unsigned long nr_segs, loff_t pos);
-static int  nfs_file_flush(struct file *, fl_owner_t id);
-static int  nfs_file_fsync(struct file *, loff_t, loff_t, int datasync);
-static int nfs_check_flags(int flags);
-static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
-static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
-static int nfs_setlease(struct file *file, long arg, struct file_lock **fl);
-
 static const struct vm_operations_struct nfs_file_vm_ops;
 
-const struct file_operations nfs_file_operations = {
-       .llseek         = nfs_file_llseek,
-       .read           = do_sync_read,
-       .write          = do_sync_write,
-       .aio_read       = nfs_file_read,
-       .aio_write      = nfs_file_write,
-       .mmap           = nfs_file_mmap,
-       .open           = nfs_file_open,
-       .flush          = nfs_file_flush,
-       .release        = nfs_file_release,
-       .fsync          = nfs_file_fsync,
-       .lock           = nfs_lock,
-       .flock          = nfs_flock,
-       .splice_read    = nfs_file_splice_read,
-       .splice_write   = nfs_file_splice_write,
-       .check_flags    = nfs_check_flags,
-       .setlease       = nfs_setlease,
-};
-
 const struct inode_operations nfs_file_inode_operations = {
        .permission     = nfs_permission,
        .getattr        = nfs_getattr,
@@ -886,3 +846,54 @@ static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
                        file->f_path.dentry->d_name.name, arg);
        return -EINVAL;
 }
+
+const struct file_operations nfs_file_operations = {
+       .llseek         = nfs_file_llseek,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
+       .aio_read       = nfs_file_read,
+       .aio_write      = nfs_file_write,
+       .mmap           = nfs_file_mmap,
+       .open           = nfs_file_open,
+       .flush          = nfs_file_flush,
+       .release        = nfs_file_release,
+       .fsync          = nfs_file_fsync,
+       .lock           = nfs_lock,
+       .flock          = nfs_flock,
+       .splice_read    = nfs_file_splice_read,
+       .splice_write   = nfs_file_splice_write,
+       .check_flags    = nfs_check_flags,
+       .setlease       = nfs_setlease,
+};
+
+#ifdef CONFIG_NFS_V4
+static int
+nfs4_file_open(struct inode *inode, struct file *filp)
+{
+       /*
+        * NFSv4 opens are handled in d_lookup and d_revalidate. If we get to
+        * this point, then something is very wrong
+        */
+       dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp);
+       return -ENOTDIR;
+}
+
+const struct file_operations nfs4_file_operations = {
+       .llseek         = nfs_file_llseek,
+       .read           = do_sync_read,
+       .write          = do_sync_write,
+       .aio_read       = nfs_file_read,
+       .aio_write      = nfs_file_write,
+       .mmap           = nfs_file_mmap,
+       .open           = nfs4_file_open,
+       .flush          = nfs_file_flush,
+       .release        = nfs_file_release,
+       .fsync          = nfs_file_fsync,
+       .lock           = nfs_lock,
+       .flock          = nfs_flock,
+       .splice_read    = nfs_file_splice_read,
+       .splice_write   = nfs_file_splice_write,
+       .check_flags    = nfs_check_flags,
+       .setlease       = nfs_setlease,
+};
+#endif /* CONFIG_NFS_V4 */
index c07a55a..50a15fa 100644 (file)
@@ -291,7 +291,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
                 */
                inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->file_inode_ops;
                if (S_ISREG(inode->i_mode)) {
-                       inode->i_fop = &nfs_file_operations;
+                       inode->i_fop = NFS_SB(sb)->nfs_client->rpc_ops->file_ops;
                        inode->i_data.a_ops = &nfs_file_aops;
                        inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info;
                } else if (S_ISDIR(inode->i_mode)) {
index c1a1bd8..3f4d957 100644 (file)
@@ -299,6 +299,8 @@ extern void nfs_read_prepare(struct rpc_task *task, void *calldata);
 extern int nfs_generic_pagein(struct nfs_pageio_descriptor *desc,
                struct list_head *head);
 
+extern void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
+               struct inode *inode);
 extern void nfs_pageio_reset_read_mds(struct nfs_pageio_descriptor *pgio);
 extern void nfs_readdata_release(struct nfs_read_data *rdata);
 
index 85f1690..d4bc9ed 100644 (file)
@@ -853,6 +853,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .dentry_ops     = &nfs_dentry_operations,
        .dir_inode_ops  = &nfs3_dir_inode_operations,
        .file_inode_ops = &nfs3_file_inode_operations,
+       .file_ops       = &nfs_file_operations,
        .getroot        = nfs3_proc_get_root,
        .getattr        = nfs3_proc_getattr,
        .setattr        = nfs3_proc_setattr,
index b60fddf..be2bbac 100644 (file)
@@ -2464,8 +2464,7 @@ static int nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qst
                case -NFS4ERR_BADNAME:
                        return -ENOENT;
                case -NFS4ERR_MOVED:
-                       err = nfs4_get_referral(dir, name, fattr, fhandle);
-                       break;
+                       return nfs4_get_referral(dir, name, fattr, fhandle);
                case -NFS4ERR_WRONGSEC:
                        nfs_fixup_secinfo_attributes(fattr, fhandle);
                }
@@ -6253,6 +6252,7 @@ const struct nfs_rpc_ops nfs_v4_clientops = {
        .dentry_ops     = &nfs4_dentry_operations,
        .dir_inode_ops  = &nfs4_dir_inode_operations,
        .file_inode_ops = &nfs4_file_inode_operations,
+       .file_ops       = &nfs4_file_operations,
        .getroot        = nfs4_proc_get_root,
        .getattr        = nfs4_proc_getattr,
        .setattr        = nfs4_proc_setattr,
index baf7353..8e672a2 100644 (file)
@@ -1260,6 +1260,25 @@ pnfs_generic_pg_writepages(struct nfs_pageio_descriptor *desc)
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_writepages);
 
+static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
+{
+       struct nfs_pageio_descriptor pgio;
+
+       put_lseg(data->lseg);
+       data->lseg = NULL;
+       dprintk("pnfs write error = %d\n", data->pnfs_error);
+
+       nfs_pageio_init_read_mds(&pgio, data->inode);
+
+       while (!list_empty(&data->pages)) {
+               struct nfs_page *req = nfs_list_entry(data->pages.next);
+
+               nfs_list_remove_request(req);
+               nfs_pageio_add_request(&pgio, req);
+       }
+       nfs_pageio_complete(&pgio);
+}
+
 /*
  * Called by non rpc-based layout drivers
  */
@@ -1268,11 +1287,8 @@ void pnfs_ld_read_done(struct nfs_read_data *data)
        if (likely(!data->pnfs_error)) {
                __nfs4_read_done_cb(data);
                data->mds_ops->rpc_call_done(&data->task, data);
-       } else {
-               put_lseg(data->lseg);
-               data->lseg = NULL;
-               dprintk("pnfs write error = %d\n", data->pnfs_error);
-       }
+       } else
+               pnfs_ld_handle_read_error(data);
        data->mds_ops->rpc_release(data);
 }
 EXPORT_SYMBOL_GPL(pnfs_ld_read_done);
index ac40b85..f48125d 100644 (file)
@@ -710,6 +710,7 @@ const struct nfs_rpc_ops nfs_v2_clientops = {
        .dentry_ops     = &nfs_dentry_operations,
        .dir_inode_ops  = &nfs_dir_inode_operations,
        .file_inode_ops = &nfs_file_inode_operations,
+       .file_ops       = &nfs_file_operations,
        .getroot        = nfs_proc_get_root,
        .getattr        = nfs_proc_getattr,
        .setattr        = nfs_proc_setattr,
index 8b48ec6..cfa175c 100644 (file)
@@ -109,7 +109,7 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data)
        }
 }
 
-static void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
+void nfs_pageio_init_read_mds(struct nfs_pageio_descriptor *pgio,
                struct inode *inode)
 {
        nfs_pageio_init(pgio, inode, &nfs_pageio_read_ops,
@@ -534,23 +534,13 @@ static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
 static void nfs_readpage_release_full(void *calldata)
 {
        struct nfs_read_data *data = calldata;
-       struct nfs_pageio_descriptor pgio;
 
-       if (data->pnfs_error) {
-               nfs_pageio_init_read_mds(&pgio, data->inode);
-               pgio.pg_recoalesce = 1;
-       }
        while (!list_empty(&data->pages)) {
                struct nfs_page *req = nfs_list_entry(data->pages.next);
 
                nfs_list_remove_request(req);
-               if (!data->pnfs_error)
-                       nfs_readpage_release(req);
-               else
-                       nfs_pageio_add_request(&pgio, req);
+               nfs_readpage_release(req);
        }
-       if (data->pnfs_error)
-               nfs_pageio_complete(&pgio);
        nfs_readdata_release(calldata);
 }
 
index 480b3b6..1347774 100644 (file)
@@ -2787,43 +2787,18 @@ static void nfs_referral_loop_unprotect(void)
 static struct dentry *nfs_follow_remote_path(struct vfsmount *root_mnt,
                const char *export_path)
 {
-       struct mnt_namespace *ns_private;
-       struct super_block *s;
        struct dentry *dentry;
-       struct path path;
-       int ret;
-
-       ns_private = create_mnt_ns(root_mnt);
-       ret = PTR_ERR(ns_private);
-       if (IS_ERR(ns_private))
-               goto out_mntput;
-
-       ret = nfs_referral_loop_protect();
-       if (ret != 0)
-               goto out_put_mnt_ns;
+       int ret = nfs_referral_loop_protect();
 
-       ret = vfs_path_lookup(root_mnt->mnt_root, root_mnt,
-                       export_path, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
+       if (ret) {
+               mntput(root_mnt);
+               return ERR_PTR(ret);
+       }
 
+       dentry = mount_subtree(root_mnt, export_path);
        nfs_referral_loop_unprotect();
-       put_mnt_ns(ns_private);
-
-       if (ret != 0)
-               goto out_err;
-
-       s = path.mnt->mnt_sb;
-       atomic_inc(&s->s_active);
-       dentry = dget(path.dentry);
 
-       path_put(&path);
-       down_write(&s->s_umount);
        return dentry;
-out_put_mnt_ns:
-       put_mnt_ns(ns_private);
-out_mntput:
-       mntput(root_mnt);
-out_err:
-       return ERR_PTR(ret);
 }
 
 static struct dentry *nfs4_try_mount(int flags, const char *dev_name,
index ed553c6..3165aeb 100644 (file)
@@ -5699,7 +5699,7 @@ int ocfs2_remove_btree_range(struct inode *inode,
                                           OCFS2_JOURNAL_ACCESS_WRITE);
        if (ret) {
                mlog_errno(ret);
-               goto out;
+               goto out_commit;
        }
 
        dquot_free_space_nodirty(inode,
index c1efe93..78b68af 100644 (file)
@@ -290,7 +290,15 @@ static int ocfs2_readpage(struct file *file, struct page *page)
        }
 
        if (down_read_trylock(&oi->ip_alloc_sem) == 0) {
+               /*
+                * Unlock the page and cycle ip_alloc_sem so that we don't
+                * busyloop waiting for ip_alloc_sem to unlock
+                */
                ret = AOP_TRUNCATED_PAGE;
+               unlock_page(page);
+               unlock = 0;
+               down_read(&oi->ip_alloc_sem);
+               up_read(&oi->ip_alloc_sem);
                goto out_inode_unlock;
        }
 
@@ -563,6 +571,7 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
 {
        struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode;
        int level;
+       wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
 
        /* this io's submitter should not have unlocked this before we could */
        BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
@@ -570,6 +579,15 @@ static void ocfs2_dio_end_io(struct kiocb *iocb,
        if (ocfs2_iocb_is_sem_locked(iocb))
                ocfs2_iocb_clear_sem_locked(iocb);
 
+       if (ocfs2_iocb_is_unaligned_aio(iocb)) {
+               ocfs2_iocb_clear_unaligned_aio(iocb);
+
+               if (atomic_dec_and_test(&OCFS2_I(inode)->ip_unaligned_aio) &&
+                   waitqueue_active(wq)) {
+                       wake_up_all(wq);
+               }
+       }
+
        ocfs2_iocb_clear_rw_locked(iocb);
 
        level = ocfs2_iocb_rw_locked_level(iocb);
@@ -862,6 +880,12 @@ struct ocfs2_write_ctxt {
        struct page                     *w_pages[OCFS2_MAX_CTXT_PAGES];
        struct page                     *w_target_page;
 
+       /*
+        * w_target_locked is used for page_mkwrite path indicating no unlocking
+        * against w_target_page in ocfs2_write_end_nolock.
+        */
+       unsigned int                    w_target_locked:1;
+
        /*
         * ocfs2_write_end() uses this to know what the real range to
         * write in the target should be.
@@ -895,6 +919,24 @@ void ocfs2_unlock_and_free_pages(struct page **pages, int num_pages)
 
 static void ocfs2_free_write_ctxt(struct ocfs2_write_ctxt *wc)
 {
+       int i;
+
+       /*
+        * w_target_locked is only set to true in the page_mkwrite() case.
+        * The intent is to allow us to lock the target page from write_begin()
+        * to write_end(). The caller must hold a ref on w_target_page.
+        */
+       if (wc->w_target_locked) {
+               BUG_ON(!wc->w_target_page);
+               for (i = 0; i < wc->w_num_pages; i++) {
+                       if (wc->w_target_page == wc->w_pages[i]) {
+                               wc->w_pages[i] = NULL;
+                               break;
+                       }
+               }
+               mark_page_accessed(wc->w_target_page);
+               page_cache_release(wc->w_target_page);
+       }
        ocfs2_unlock_and_free_pages(wc->w_pages, wc->w_num_pages);
 
        brelse(wc->w_di_bh);
@@ -1132,20 +1174,17 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
                         */
                        lock_page(mmap_page);
 
+                       /* Exit and let the caller retry */
                        if (mmap_page->mapping != mapping) {
+                               WARN_ON(mmap_page->mapping);
                                unlock_page(mmap_page);
-                               /*
-                                * Sanity check - the locking in
-                                * ocfs2_pagemkwrite() should ensure
-                                * that this code doesn't trigger.
-                                */
-                               ret = -EINVAL;
-                               mlog_errno(ret);
+                               ret = -EAGAIN;
                                goto out;
                        }
 
                        page_cache_get(mmap_page);
                        wc->w_pages[i] = mmap_page;
+                       wc->w_target_locked = true;
                } else {
                        wc->w_pages[i] = find_or_create_page(mapping, index,
                                                             GFP_NOFS);
@@ -1160,6 +1199,8 @@ static int ocfs2_grab_pages_for_write(struct address_space *mapping,
                        wc->w_target_page = wc->w_pages[i];
        }
 out:
+       if (ret)
+               wc->w_target_locked = false;
        return ret;
 }
 
@@ -1817,11 +1858,23 @@ try_again:
         */
        ret = ocfs2_grab_pages_for_write(mapping, wc, wc->w_cpos, pos, len,
                                         cluster_of_pages, mmap_page);
-       if (ret) {
+       if (ret && ret != -EAGAIN) {
                mlog_errno(ret);
                goto out_quota;
        }
 
+       /*
+        * ocfs2_grab_pages_for_write() returns -EAGAIN if it could not lock
+        * the target page. In this case, we exit with no error and no target
+        * page. This will trigger the caller, page_mkwrite(), to re-try
+        * the operation.
+        */
+       if (ret == -EAGAIN) {
+               BUG_ON(wc->w_target_page);
+               ret = 0;
+               goto out_quota;
+       }
+
        ret = ocfs2_write_cluster_by_desc(mapping, data_ac, meta_ac, wc, pos,
                                          len);
        if (ret) {
index 75cf3ad..ffb2da3 100644 (file)
@@ -78,6 +78,7 @@ enum ocfs2_iocb_lock_bits {
        OCFS2_IOCB_RW_LOCK = 0,
        OCFS2_IOCB_RW_LOCK_LEVEL,
        OCFS2_IOCB_SEM,
+       OCFS2_IOCB_UNALIGNED_IO,
        OCFS2_IOCB_NUM_LOCKS
 };
 
@@ -91,4 +92,17 @@ enum ocfs2_iocb_lock_bits {
        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)
+
+#define ocfs2_iocb_set_unaligned_aio(iocb) \
+       set_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_clear_unaligned_aio(iocb) \
+       clear_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
+#define ocfs2_iocb_is_unaligned_aio(iocb) \
+       test_bit(OCFS2_IOCB_UNALIGNED_IO, (unsigned long *)&iocb->private)
+
+#define OCFS2_IOEND_WQ_HASH_SZ 37
+#define ocfs2_ioend_wq(v)   (&ocfs2__ioend_wq[((unsigned long)(v)) %\
+                                           OCFS2_IOEND_WQ_HASH_SZ])
+extern wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ];
+
 #endif /* OCFS2_FILE_H */
index 9a3e6bb..a4e855e 100644 (file)
@@ -216,6 +216,7 @@ struct o2hb_region {
 
        struct list_head        hr_all_item;
        unsigned                hr_unclean_stop:1,
+                               hr_aborted_start:1,
                                hr_item_pinned:1,
                                hr_item_dropped:1;
 
@@ -254,6 +255,10 @@ struct o2hb_region {
         * a more complete api that doesn't lead to this sort of fragility. */
        atomic_t                hr_steady_iterations;
 
+       /* terminate o2hb thread if it does not reach steady state
+        * (hr_steady_iterations == 0) within hr_unsteady_iterations */
+       atomic_t                hr_unsteady_iterations;
+
        char                    hr_dev_name[BDEVNAME_SIZE];
 
        unsigned int            hr_timeout_ms;
@@ -324,6 +329,10 @@ static void o2hb_write_timeout(struct work_struct *work)
 
 static void o2hb_arm_write_timeout(struct o2hb_region *reg)
 {
+       /* Arm writeout only after thread reaches steady state */
+       if (atomic_read(&reg->hr_steady_iterations) != 0)
+               return;
+
        mlog(ML_HEARTBEAT, "Queue write timeout for %u ms\n",
             O2HB_MAX_WRITE_TIMEOUT_MS);
 
@@ -537,9 +546,14 @@ static int o2hb_verify_crc(struct o2hb_region *reg,
        return read == computed;
 }
 
-/* We want to make sure that nobody is heartbeating on top of us --
- * this will help detect an invalid configuration. */
-static void o2hb_check_last_timestamp(struct o2hb_region *reg)
+/*
+ * Compare the slot data with what we wrote in the last iteration.
+ * If the match fails, print an appropriate error message. This is to
+ * detect errors like... another node hearting on the same slot,
+ * flaky device that is losing writes, etc.
+ * Returns 1 if check succeeds, 0 otherwise.
+ */
+static int o2hb_check_own_slot(struct o2hb_region *reg)
 {
        struct o2hb_disk_slot *slot;
        struct o2hb_disk_heartbeat_block *hb_block;
@@ -548,13 +562,13 @@ static void o2hb_check_last_timestamp(struct o2hb_region *reg)
        slot = &reg->hr_slots[o2nm_this_node()];
        /* Don't check on our 1st timestamp */
        if (!slot->ds_last_time)
-               return;
+               return 0;
 
        hb_block = slot->ds_raw_block;
        if (le64_to_cpu(hb_block->hb_seq) == slot->ds_last_time &&
            le64_to_cpu(hb_block->hb_generation) == slot->ds_last_generation &&
            hb_block->hb_node == slot->ds_node_num)
-               return;
+               return 1;
 
 #define ERRSTR1                "Another node is heartbeating on device"
 #define ERRSTR2                "Heartbeat generation mismatch on device"
@@ -574,6 +588,8 @@ static void o2hb_check_last_timestamp(struct o2hb_region *reg)
             (unsigned long long)slot->ds_last_time, hb_block->hb_node,
             (unsigned long long)le64_to_cpu(hb_block->hb_generation),
             (unsigned long long)le64_to_cpu(hb_block->hb_seq));
+
+       return 0;
 }
 
 static inline void o2hb_prepare_block(struct o2hb_region *reg,
@@ -719,17 +735,24 @@ static void o2hb_shutdown_slot(struct o2hb_disk_slot *slot)
        o2nm_node_put(node);
 }
 
-static void o2hb_set_quorum_device(struct o2hb_region *reg,
-                                  struct o2hb_disk_slot *slot)
+static void o2hb_set_quorum_device(struct o2hb_region *reg)
 {
-       assert_spin_locked(&o2hb_live_lock);
-
        if (!o2hb_global_heartbeat_active())
                return;
 
-       if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+       /* Prevent race with o2hb_heartbeat_group_drop_item() */
+       if (kthread_should_stop())
+               return;
+
+       /* Tag region as quorum only after thread reaches steady state */
+       if (atomic_read(&reg->hr_steady_iterations) != 0)
                return;
 
+       spin_lock(&o2hb_live_lock);
+
+       if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+               goto unlock;
+
        /*
         * A region can be added to the quorum only when it sees all
         * live nodes heartbeat on it. In other words, the region has been
@@ -737,13 +760,10 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg,
         */
        if (memcmp(reg->hr_live_node_bitmap, o2hb_live_node_bitmap,
                   sizeof(o2hb_live_node_bitmap)))
-               return;
-
-       if (slot->ds_changed_samples < O2HB_LIVE_THRESHOLD)
-               return;
+               goto unlock;
 
-       printk(KERN_NOTICE "o2hb: Region %s is now a quorum device\n",
-              config_item_name(&reg->hr_item));
+       printk(KERN_NOTICE "o2hb: Region %s (%s) is now a quorum device\n",
+              config_item_name(&reg->hr_item), reg->hr_dev_name);
 
        set_bit(reg->hr_region_num, o2hb_quorum_region_bitmap);
 
@@ -754,6 +774,8 @@ static void o2hb_set_quorum_device(struct o2hb_region *reg,
        if (o2hb_pop_count(&o2hb_quorum_region_bitmap,
                           O2NM_MAX_REGIONS) > O2HB_PIN_CUT_OFF)
                o2hb_region_unpin(NULL);
+unlock:
+       spin_unlock(&o2hb_live_lock);
 }
 
 static int o2hb_check_slot(struct o2hb_region *reg,
@@ -925,8 +947,6 @@ fire_callbacks:
                slot->ds_equal_samples = 0;
        }
 out:
-       o2hb_set_quorum_device(reg, slot);
-
        spin_unlock(&o2hb_live_lock);
 
        o2hb_run_event_list(&event);
@@ -957,7 +977,8 @@ static int o2hb_highest_node(unsigned long *nodes,
 
 static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
 {
-       int i, ret, highest_node, change = 0;
+       int i, ret, highest_node;
+       int membership_change = 0, own_slot_ok = 0;
        unsigned long configured_nodes[BITS_TO_LONGS(O2NM_MAX_NODES)];
        unsigned long live_node_bitmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
        struct o2hb_bio_wait_ctxt write_wc;
@@ -966,7 +987,7 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
                                       sizeof(configured_nodes));
        if (ret) {
                mlog_errno(ret);
-               return ret;
+               goto bail;
        }
 
        /*
@@ -982,8 +1003,9 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
 
        highest_node = o2hb_highest_node(configured_nodes, O2NM_MAX_NODES);
        if (highest_node >= O2NM_MAX_NODES) {
-               mlog(ML_NOTICE, "ocfs2_heartbeat: no configured nodes found!\n");
-               return -EINVAL;
+               mlog(ML_NOTICE, "o2hb: No configured nodes found!\n");
+               ret = -EINVAL;
+               goto bail;
        }
 
        /* No sense in reading the slots of nodes that don't exist
@@ -993,29 +1015,27 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
        ret = o2hb_read_slots(reg, highest_node + 1);
        if (ret < 0) {
                mlog_errno(ret);
-               return ret;
+               goto bail;
        }
 
        /* With an up to date view of the slots, we can check that no
         * other node has been improperly configured to heartbeat in
         * our slot. */
-       o2hb_check_last_timestamp(reg);
+       own_slot_ok = o2hb_check_own_slot(reg);
 
        /* fill in the proper info for our next heartbeat */
        o2hb_prepare_block(reg, reg->hr_generation);
 
-       /* And fire off the write. Note that we don't wait on this I/O
-        * until later. */
        ret = o2hb_issue_node_write(reg, &write_wc);
        if (ret < 0) {
                mlog_errno(ret);
-               return ret;
+               goto bail;
        }
 
        i = -1;
        while((i = find_next_bit(configured_nodes,
                                 O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES) {
-               change |= o2hb_check_slot(reg, &reg->hr_slots[i]);
+               membership_change |= o2hb_check_slot(reg, &reg->hr_slots[i]);
        }
 
        /*
@@ -1030,18 +1050,39 @@ static int o2hb_do_disk_heartbeat(struct o2hb_region *reg)
                 * disk */
                mlog(ML_ERROR, "Write error %d on device \"%s\"\n",
                     write_wc.wc_error, reg->hr_dev_name);
-               return write_wc.wc_error;
+               ret = write_wc.wc_error;
+               goto bail;
        }
 
-       o2hb_arm_write_timeout(reg);
+       /* Skip disarming the timeout if own slot has stale/bad data */
+       if (own_slot_ok) {
+               o2hb_set_quorum_device(reg);
+               o2hb_arm_write_timeout(reg);
+       }
 
+bail:
        /* let the person who launched us know when things are steady */
-       if (!change && (atomic_read(&reg->hr_steady_iterations) != 0)) {
-               if (atomic_dec_and_test(&reg->hr_steady_iterations))
+       if (atomic_read(&reg->hr_steady_iterations) != 0) {
+               if (!ret && own_slot_ok && !membership_change) {
+                       if (atomic_dec_and_test(&reg->hr_steady_iterations))
+                               wake_up(&o2hb_steady_queue);
+               }
+       }
+
+       if (atomic_read(&reg->hr_steady_iterations) != 0) {
+               if (atomic_dec_and_test(&reg->hr_unsteady_iterations)) {
+                       printk(KERN_NOTICE "o2hb: Unable to stabilize "
+                              "heartbeart on region %s (%s)\n",
+                              config_item_name(&reg->hr_item),
+                              reg->hr_dev_name);
+                       atomic_set(&reg->hr_steady_iterations, 0);
+                       reg->hr_aborted_start = 1;
                        wake_up(&o2hb_steady_queue);
+                       ret = -EIO;
+               }
        }
 
-       return 0;
+       return ret;
 }
 
 /* Subtract b from a, storing the result in a. a *must* have a larger
@@ -1095,7 +1136,8 @@ static int o2hb_thread(void *data)
        /* Pin node */
        o2nm_depend_this_node();
 
-       while (!kthread_should_stop() && !reg->hr_unclean_stop) {
+       while (!kthread_should_stop() &&
+              !reg->hr_unclean_stop && !reg->hr_aborted_start) {
                /* We track the time spent inside
                 * o2hb_do_disk_heartbeat so that we avoid more than
                 * hr_timeout_ms between disk writes. On busy systems
@@ -1103,10 +1145,7 @@ static int o2hb_thread(void *data)
                 * likely to time itself out. */
                do_gettimeofday(&before_hb);
 
-               i = 0;
-               do {
-                       ret = o2hb_do_disk_heartbeat(reg);
-               } while (ret && ++i < 2);
+               ret = o2hb_do_disk_heartbeat(reg);
 
                do_gettimeofday(&after_hb);
                elapsed_msec = o2hb_elapsed_msecs(&before_hb, &after_hb);
@@ -1117,7 +1156,8 @@ static int o2hb_thread(void *data)
                     after_hb.tv_sec, (unsigned long) after_hb.tv_usec,
                     elapsed_msec);
 
-               if (elapsed_msec < reg->hr_timeout_ms) {
+               if (!kthread_should_stop() &&
+                   elapsed_msec < reg->hr_timeout_ms) {
                        /* the kthread api has blocked signals for us so no
                         * need to record the return value. */
                        msleep_interruptible(reg->hr_timeout_ms - elapsed_msec);
@@ -1134,20 +1174,20 @@ static int o2hb_thread(void *data)
         * to timeout on this region when we could just as easily
         * write a clear generation - thus indicating to them that
         * this node has left this region.
-        *
-        * XXX: Should we skip this on unclean_stop? */
-       o2hb_prepare_block(reg, 0);
-       ret = o2hb_issue_node_write(reg, &write_wc);
-       if (ret == 0) {
-               o2hb_wait_on_io(reg, &write_wc);
-       } else {
-               mlog_errno(ret);
+        */
+       if (!reg->hr_unclean_stop && !reg->hr_aborted_start) {
+               o2hb_prepare_block(reg, 0);
+               ret = o2hb_issue_node_write(reg, &write_wc);
+               if (ret == 0)
+                       o2hb_wait_on_io(reg, &write_wc);
+               else
+                       mlog_errno(ret);
        }
 
        /* Unpin node */
        o2nm_undepend_this_node();
 
-       mlog(ML_HEARTBEAT|ML_KTHREAD, "hb thread exiting\n");
+       mlog(ML_HEARTBEAT|ML_KTHREAD, "o2hb thread exiting\n");
 
        return 0;
 }
@@ -1158,6 +1198,7 @@ static int o2hb_debug_open(struct inode *inode, struct file *file)
        struct o2hb_debug_buf *db = inode->i_private;
        struct o2hb_region *reg;
        unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+       unsigned long lts;
        char *buf = NULL;
        int i = -1;
        int out = 0;
@@ -1194,9 +1235,11 @@ static int o2hb_debug_open(struct inode *inode, struct file *file)
 
        case O2HB_DB_TYPE_REGION_ELAPSED_TIME:
                reg = (struct o2hb_region *)db->db_data;
-               out += snprintf(buf + out, PAGE_SIZE - out, "%u\n",
-                               jiffies_to_msecs(jiffies -
-                                                reg->hr_last_timeout_start));
+               lts = reg->hr_last_timeout_start;
+               /* If 0, it has never been set before */
+               if (lts)
+                       lts = jiffies_to_msecs(jiffies - lts);
+               out += snprintf(buf + out, PAGE_SIZE - out, "%lu\n", lts);
                goto done;
 
        case O2HB_DB_TYPE_REGION_PINNED:
@@ -1426,6 +1469,8 @@ static void o2hb_region_release(struct config_item *item)
        struct page *page;
        struct o2hb_region *reg = to_o2hb_region(item);
 
+       mlog(ML_HEARTBEAT, "hb region release (%s)\n", reg->hr_dev_name);
+
        if (reg->hr_tmp_block)
                kfree(reg->hr_tmp_block);
 
@@ -1792,7 +1837,10 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
                        live_threshold <<= 1;
                spin_unlock(&o2hb_live_lock);
        }
-       atomic_set(&reg->hr_steady_iterations, live_threshold + 1);
+       ++live_threshold;
+       atomic_set(&reg->hr_steady_iterations, live_threshold);
+       /* unsteady_iterations is double the steady_iterations */
+       atomic_set(&reg->hr_unsteady_iterations, (live_threshold << 1));
 
        hb_task = kthread_run(o2hb_thread, reg, "o2hb-%s",
                              reg->hr_item.ci_name);
@@ -1809,14 +1857,12 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
        ret = wait_event_interruptible(o2hb_steady_queue,
                                atomic_read(&reg->hr_steady_iterations) == 0);
        if (ret) {
-               /* We got interrupted (hello ptrace!).  Clean up */
-               spin_lock(&o2hb_live_lock);
-               hb_task = reg->hr_task;
-               reg->hr_task = NULL;
-               spin_unlock(&o2hb_live_lock);
+               atomic_set(&reg->hr_steady_iterations, 0);
+               reg->hr_aborted_start = 1;
+       }
 
-               if (hb_task)
-                       kthread_stop(hb_task);
+       if (reg->hr_aborted_start) {
+               ret = -EIO;
                goto out;
        }
 
@@ -1833,8 +1879,8 @@ static ssize_t o2hb_region_dev_write(struct o2hb_region *reg,
                ret = -EIO;
 
        if (hb_task && o2hb_global_heartbeat_active())
-               printk(KERN_NOTICE "o2hb: Heartbeat started on region %s\n",
-                      config_item_name(&reg->hr_item));
+               printk(KERN_NOTICE "o2hb: Heartbeat started on region %s (%s)\n",
+                      config_item_name(&reg->hr_item), reg->hr_dev_name);
 
 out:
        if (filp)
@@ -2092,13 +2138,6 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
 
        /* stop the thread when the user removes the region dir */
        spin_lock(&o2hb_live_lock);
-       if (o2hb_global_heartbeat_active()) {
-               clear_bit(reg->hr_region_num, o2hb_region_bitmap);
-               clear_bit(reg->hr_region_num, o2hb_live_region_bitmap);
-               if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
-                       quorum_region = 1;
-               clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap);
-       }
        hb_task = reg->hr_task;
        reg->hr_task = NULL;
        reg->hr_item_dropped = 1;
@@ -2107,19 +2146,30 @@ static void o2hb_heartbeat_group_drop_item(struct config_group *group,
        if (hb_task)
                kthread_stop(hb_task);
 
+       if (o2hb_global_heartbeat_active()) {
+               spin_lock(&o2hb_live_lock);
+               clear_bit(reg->hr_region_num, o2hb_region_bitmap);
+               clear_bit(reg->hr_region_num, o2hb_live_region_bitmap);
+               if (test_bit(reg->hr_region_num, o2hb_quorum_region_bitmap))
+                       quorum_region = 1;
+               clear_bit(reg->hr_region_num, o2hb_quorum_region_bitmap);
+               spin_unlock(&o2hb_live_lock);
+               printk(KERN_NOTICE "o2hb: Heartbeat %s on region %s (%s)\n",
+                      ((atomic_read(&reg->hr_steady_iterations) == 0) ?
+                       "stopped" : "start aborted"), config_item_name(item),
+                      reg->hr_dev_name);
+       }
+
        /*
         * If we're racing a dev_write(), we need to wake them.  They will
         * check reg->hr_task
         */
        if (atomic_read(&reg->hr_steady_iterations) != 0) {
+               reg->hr_aborted_start = 1;
                atomic_set(&reg->hr_steady_iterations, 0);
                wake_up(&o2hb_steady_queue);
        }
 
-       if (o2hb_global_heartbeat_active())
-               printk(KERN_NOTICE "o2hb: Heartbeat stopped on region %s\n",
-                      config_item_name(&reg->hr_item));
-
        config_item_put(item);
 
        if (!o2hb_global_heartbeat_active() || !quorum_region)
index 3a58359..dc45deb 100644 (file)
@@ -47,6 +47,7 @@
 #define SC_DEBUG_NAME          "sock_containers"
 #define NST_DEBUG_NAME         "send_tracking"
 #define STATS_DEBUG_NAME       "stats"
+#define NODES_DEBUG_NAME       "connected_nodes"
 
 #define SHOW_SOCK_CONTAINERS   0
 #define SHOW_SOCK_STATS                1
@@ -55,6 +56,7 @@ static struct dentry *o2net_dentry;
 static struct dentry *sc_dentry;
 static struct dentry *nst_dentry;
 static struct dentry *stats_dentry;
+static struct dentry *nodes_dentry;
 
 static DEFINE_SPINLOCK(o2net_debug_lock);
 
@@ -491,53 +493,87 @@ static const struct file_operations sc_seq_fops = {
        .release = sc_fop_release,
 };
 
-int o2net_debugfs_init(void)
+static int o2net_fill_bitmap(char *buf, int len)
 {
-       o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL);
-       if (!o2net_dentry) {
-               mlog_errno(-ENOMEM);
-               goto bail;
-       }
+       unsigned long map[BITS_TO_LONGS(O2NM_MAX_NODES)];
+       int i = -1, out = 0;
 
-       nst_dentry = debugfs_create_file(NST_DEBUG_NAME, S_IFREG|S_IRUSR,
-                                        o2net_dentry, NULL,
-                                        &nst_seq_fops);
-       if (!nst_dentry) {
-               mlog_errno(-ENOMEM);
-               goto bail;
-       }
+       o2net_fill_node_map(map, sizeof(map));
 
-       sc_dentry = debugfs_create_file(SC_DEBUG_NAME, S_IFREG|S_IRUSR,
-                                       o2net_dentry, NULL,
-                                       &sc_seq_fops);
-       if (!sc_dentry) {
-               mlog_errno(-ENOMEM);
-               goto bail;
-       }
+       while ((i = find_next_bit(map, O2NM_MAX_NODES, i + 1)) < O2NM_MAX_NODES)
+               out += snprintf(buf + out, PAGE_SIZE - out, "%d ", i);
+       out += snprintf(buf + out, PAGE_SIZE - out, "\n");
 
-       stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, S_IFREG|S_IRUSR,
-                                          o2net_dentry, NULL,
-                                          &stats_seq_fops);
-       if (!stats_dentry) {
-               mlog_errno(-ENOMEM);
-               goto bail;
-       }
+       return out;
+}
+
+static int nodes_fop_open(struct inode *inode, struct file *file)
+{
+       char *buf;
+
+       buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       i_size_write(inode, o2net_fill_bitmap(buf, PAGE_SIZE));
+
+       file->private_data = buf;
 
        return 0;
-bail:
-       debugfs_remove(stats_dentry);
-       debugfs_remove(sc_dentry);
-       debugfs_remove(nst_dentry);
-       debugfs_remove(o2net_dentry);
-       return -ENOMEM;
 }
 
+static int o2net_debug_release(struct inode *inode, struct file *file)
+{
+       kfree(file->private_data);
+       return 0;
+}
+
+static ssize_t o2net_debug_read(struct file *file, char __user *buf,
+                               size_t nbytes, loff_t *ppos)
+{
+       return simple_read_from_buffer(buf, nbytes, ppos, file->private_data,
+                                      i_size_read(file->f_mapping->host));
+}
+
+static const struct file_operations nodes_fops = {
+       .open           = nodes_fop_open,
+       .release        = o2net_debug_release,
+       .read           = o2net_debug_read,
+       .llseek         = generic_file_llseek,
+};
+
 void o2net_debugfs_exit(void)
 {
+       debugfs_remove(nodes_dentry);
        debugfs_remove(stats_dentry);
        debugfs_remove(sc_dentry);
        debugfs_remove(nst_dentry);
        debugfs_remove(o2net_dentry);
 }
 
+int o2net_debugfs_init(void)
+{
+       mode_t mode = S_IFREG|S_IRUSR;
+
+       o2net_dentry = debugfs_create_dir(O2NET_DEBUG_DIR, NULL);
+       if (o2net_dentry)
+               nst_dentry = debugfs_create_file(NST_DEBUG_NAME, mode,
+                                       o2net_dentry, NULL, &nst_seq_fops);
+       if (nst_dentry)
+               sc_dentry = debugfs_create_file(SC_DEBUG_NAME, mode,
+                                       o2net_dentry, NULL, &sc_seq_fops);
+       if (sc_dentry)
+               stats_dentry = debugfs_create_file(STATS_DEBUG_NAME, mode,
+                                       o2net_dentry, NULL, &stats_seq_fops);
+       if (stats_dentry)
+               nodes_dentry = debugfs_create_file(NODES_DEBUG_NAME, mode,
+                                       o2net_dentry, NULL, &nodes_fops);
+       if (nodes_dentry)
+               return 0;
+
+       o2net_debugfs_exit();
+       mlog_errno(-ENOMEM);
+       return -ENOMEM;
+}
+
 #endif /* CONFIG_DEBUG_FS */
index ad7d0c1..044e7b5 100644 (file)
@@ -546,7 +546,7 @@ static void o2net_set_nn_state(struct o2net_node *nn,
        }
 
        if (was_valid && !valid) {
-               printk(KERN_NOTICE "o2net: no longer connected to "
+               printk(KERN_NOTICE "o2net: No longer connected to "
                       SC_NODEF_FMT "\n", SC_NODEF_ARGS(old_sc));
                o2net_complete_nodes_nsw(nn);
        }
@@ -556,7 +556,7 @@ static void o2net_set_nn_state(struct o2net_node *nn,
                cancel_delayed_work(&nn->nn_connect_expired);
                printk(KERN_NOTICE "o2net: %s " SC_NODEF_FMT "\n",
                       o2nm_this_node() > sc->sc_node->nd_num ?
-                               "connected to" : "accepted connection from",
+                      "Connected to" : "Accepted connection from",
                       SC_NODEF_ARGS(sc));
        }
 
@@ -644,7 +644,7 @@ static void o2net_state_change(struct sock *sk)
                        o2net_sc_queue_work(sc, &sc->sc_connect_work);
                        break;
                default:
-                       printk(KERN_INFO "o2net: connection to " SC_NODEF_FMT
+                       printk(KERN_INFO "o2net: Connection to " SC_NODEF_FMT
                              " shutdown, state %d\n",
                              SC_NODEF_ARGS(sc), sk->sk_state);
                        o2net_sc_queue_work(sc, &sc->sc_shutdown_work);
@@ -1035,6 +1035,25 @@ static int o2net_tx_can_proceed(struct o2net_node *nn,
        return ret;
 }
 
+/* Get a map of all nodes to which this node is currently connected to */
+void o2net_fill_node_map(unsigned long *map, unsigned bytes)
+{
+       struct o2net_sock_container *sc;
+       int node, ret;
+
+       BUG_ON(bytes < (BITS_TO_LONGS(O2NM_MAX_NODES) * sizeof(unsigned long)));
+
+       memset(map, 0, bytes);
+       for (node = 0; node < O2NM_MAX_NODES; ++node) {
+               o2net_tx_can_proceed(o2net_nn_from_num(node), &sc, &ret);
+               if (!ret) {
+                       set_bit(node, map);
+                       sc_put(sc);
+               }
+       }
+}
+EXPORT_SYMBOL_GPL(o2net_fill_node_map);
+
 int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
                           size_t caller_veclen, u8 target_node, int *status)
 {
@@ -1285,11 +1304,11 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
        struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
 
        if (hand->protocol_version != cpu_to_be64(O2NET_PROTOCOL_VERSION)) {
-               mlog(ML_NOTICE, SC_NODEF_FMT " advertised net protocol "
-                    "version %llu but %llu is required, disconnecting\n",
-                    SC_NODEF_ARGS(sc),
-                    (unsigned long long)be64_to_cpu(hand->protocol_version),
-                    O2NET_PROTOCOL_VERSION);
+               printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " Advertised net "
+                      "protocol version %llu but %llu is required. "
+                      "Disconnecting.\n", SC_NODEF_ARGS(sc),
+                      (unsigned long long)be64_to_cpu(hand->protocol_version),
+                      O2NET_PROTOCOL_VERSION);
 
                /* don't bother reconnecting if its the wrong version. */
                o2net_ensure_shutdown(nn, sc, -ENOTCONN);
@@ -1303,33 +1322,33 @@ static int o2net_check_handshake(struct o2net_sock_container *sc)
         */
        if (be32_to_cpu(hand->o2net_idle_timeout_ms) !=
                                o2net_idle_timeout()) {
-               mlog(ML_NOTICE, SC_NODEF_FMT " uses a network idle timeout of "
-                    "%u ms, but we use %u ms locally.  disconnecting\n",
-                    SC_NODEF_ARGS(sc),
-                    be32_to_cpu(hand->o2net_idle_timeout_ms),
-                    o2net_idle_timeout());
+               printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a network "
+                      "idle timeout of %u ms, but we use %u ms locally. "
+                      "Disconnecting.\n", SC_NODEF_ARGS(sc),
+                      be32_to_cpu(hand->o2net_idle_timeout_ms),
+                      o2net_idle_timeout());
                o2net_ensure_shutdown(nn, sc, -ENOTCONN);
                return -1;
        }
 
        if (be32_to_cpu(hand->o2net_keepalive_delay_ms) !=
                        o2net_keepalive_delay()) {
-               mlog(ML_NOTICE, SC_NODEF_FMT " uses a keepalive delay of "
-                    "%u ms, but we use %u ms locally.  disconnecting\n",
-                    SC_NODEF_ARGS(sc),
-                    be32_to_cpu(hand->o2net_keepalive_delay_ms),
-                    o2net_keepalive_delay());
+               printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a keepalive "
+                      "delay of %u ms, but we use %u ms locally. "
+                      "Disconnecting.\n", SC_NODEF_ARGS(sc),
+                      be32_to_cpu(hand->o2net_keepalive_delay_ms),
+                      o2net_keepalive_delay());
                o2net_ensure_shutdown(nn, sc, -ENOTCONN);
                return -1;
        }
 
        if (be32_to_cpu(hand->o2hb_heartbeat_timeout_ms) !=
                        O2HB_MAX_WRITE_TIMEOUT_MS) {
-               mlog(ML_NOTICE, SC_NODEF_FMT " uses a heartbeat timeout of "
-                    "%u ms, but we use %u ms locally.  disconnecting\n",
-                    SC_NODEF_ARGS(sc),
-                    be32_to_cpu(hand->o2hb_heartbeat_timeout_ms),
-                    O2HB_MAX_WRITE_TIMEOUT_MS);
+               printk(KERN_NOTICE "o2net: " SC_NODEF_FMT " uses a heartbeat "
+                      "timeout of %u ms, but we use %u ms locally. "
+                      "Disconnecting.\n", SC_NODEF_ARGS(sc),
+                      be32_to_cpu(hand->o2hb_heartbeat_timeout_ms),
+                      O2HB_MAX_WRITE_TIMEOUT_MS);
                o2net_ensure_shutdown(nn, sc, -ENOTCONN);
                return -1;
        }
@@ -1540,28 +1559,16 @@ static void o2net_idle_timer(unsigned long data)
 {
        struct o2net_sock_container *sc = (struct o2net_sock_container *)data;
        struct o2net_node *nn = o2net_nn_from_num(sc->sc_node->nd_num);
-
 #ifdef CONFIG_DEBUG_FS
-       ktime_t now = ktime_get();
+       unsigned long msecs = ktime_to_ms(ktime_get()) -
+               ktime_to_ms(sc->sc_tv_timer);
+#else
+       unsigned long msecs = o2net_idle_timeout();
 #endif
 
-       printk(KERN_NOTICE "o2net: connection to " SC_NODEF_FMT " has been idle for %u.%u "
-            "seconds, shutting it down.\n", SC_NODEF_ARGS(sc),
-                    o2net_idle_timeout() / 1000,
-                    o2net_idle_timeout() % 1000);
-
-#ifdef CONFIG_DEBUG_FS
-       mlog(ML_NOTICE, "Here are some times that might help debug the "
-            "situation: (Timer: %lld, Now %lld, DataReady %lld, Advance %lld-%lld, "
-            "Key 0x%08x, Func %u, FuncTime %lld-%lld)\n",
-            (long long)ktime_to_us(sc->sc_tv_timer), (long long)ktime_to_us(now),
-            (long long)ktime_to_us(sc->sc_tv_data_ready),
-            (long long)ktime_to_us(sc->sc_tv_advance_start),
-            (long long)ktime_to_us(sc->sc_tv_advance_stop),
-            sc->sc_msg_key, sc->sc_msg_type,
-            (long long)ktime_to_us(sc->sc_tv_func_start),
-            (long long)ktime_to_us(sc->sc_tv_func_stop));
-#endif
+       printk(KERN_NOTICE "o2net: Connection to " SC_NODEF_FMT " has been "
+              "idle for %lu.%lu secs, shutting it down.\n", SC_NODEF_ARGS(sc),
+              msecs / 1000, msecs % 1000);
 
        /*
         * Initialize the nn_timeout so that the next connection attempt
@@ -1694,8 +1701,8 @@ static void o2net_start_connect(struct work_struct *work)
 
 out:
        if (ret) {
-               mlog(ML_NOTICE, "connect attempt to " SC_NODEF_FMT " failed "
-                    "with errno %d\n", SC_NODEF_ARGS(sc), ret);
+               printk(KERN_NOTICE "o2net: Connect attempt to " SC_NODEF_FMT
+                      " failed with errno %d\n", SC_NODEF_ARGS(sc), ret);
                /* 0 err so that another will be queued and attempted
                 * from set_nn_state */
                if (sc)
@@ -1718,8 +1725,8 @@ static void o2net_connect_expired(struct work_struct *work)
 
        spin_lock(&nn->nn_lock);
        if (!nn->nn_sc_valid) {
-               mlog(ML_ERROR, "no connection established with node %u after "
-                    "%u.%u seconds, giving up and returning errors.\n",
+               printk(KERN_NOTICE "o2net: No connection established with "
+                      "node %u after %u.%u seconds, giving up.\n",
                     o2net_num_from_nn(nn),
                     o2net_idle_timeout() / 1000,
                     o2net_idle_timeout() % 1000);
@@ -1862,21 +1869,21 @@ static int o2net_accept_one(struct socket *sock)
 
        node = o2nm_get_node_by_ip(sin.sin_addr.s_addr);
        if (node == NULL) {
-               mlog(ML_NOTICE, "attempt to connect from unknown node at %pI4:%d\n",
-                    &sin.sin_addr.s_addr, ntohs(sin.sin_port));
+               printk(KERN_NOTICE "o2net: Attempt to connect from unknown "
+                      "node at %pI4:%d\n", &sin.sin_addr.s_addr,
+                      ntohs(sin.sin_port));
                ret = -EINVAL;
                goto out;
        }
 
        if (o2nm_this_node() >= node->nd_num) {
                local_node = o2nm_get_node_by_num(o2nm_this_node());
-               mlog(ML_NOTICE, "unexpected connect attempt seen at node '%s' ("
-                    "%u, %pI4:%d) from node '%s' (%u, %pI4:%d)\n",
-                    local_node->nd_name, local_node->nd_num,
-                    &(local_node->nd_ipv4_address),
-                    ntohs(local_node->nd_ipv4_port),
-                    node->nd_name, node->nd_num, &sin.sin_addr.s_addr,
-                    ntohs(sin.sin_port));
+               printk(KERN_NOTICE "o2net: Unexpected connect attempt seen "
+                      "at node '%s' (%u, %pI4:%d) from node '%s' (%u, "
+                      "%pI4:%d)\n", local_node->nd_name, local_node->nd_num,
+                      &(local_node->nd_ipv4_address),
+                      ntohs(local_node->nd_ipv4_port), node->nd_name,
+                      node->nd_num, &sin.sin_addr.s_addr, ntohs(sin.sin_port));
                ret = -EINVAL;
                goto out;
        }
@@ -1901,10 +1908,10 @@ static int o2net_accept_one(struct socket *sock)
                ret = 0;
        spin_unlock(&nn->nn_lock);
        if (ret) {
-               mlog(ML_NOTICE, "attempt to connect from node '%s' at "
-                    "%pI4:%d but it already has an open connection\n",
-                    node->nd_name, &sin.sin_addr.s_addr,
-                    ntohs(sin.sin_port));
+               printk(KERN_NOTICE "o2net: Attempt to connect from node '%s' "
+                      "at %pI4:%d but it already has an open connection\n",
+                      node->nd_name, &sin.sin_addr.s_addr,
+                      ntohs(sin.sin_port));
                goto out;
        }
 
@@ -1984,7 +1991,7 @@ static int o2net_open_listening_sock(__be32 addr, __be16 port)
 
        ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
        if (ret < 0) {
-               mlog(ML_ERROR, "unable to create socket, ret=%d\n", ret);
+               printk(KERN_ERR "o2net: Error %d while creating socket\n", ret);
                goto out;
        }
 
@@ -2001,16 +2008,15 @@ static int o2net_open_listening_sock(__be32 addr, __be16 port)
        sock->sk->sk_reuse = 1;
        ret = sock->ops->bind(sock, (struct sockaddr *)&sin, sizeof(sin));
        if (ret < 0) {
-               mlog(ML_ERROR, "unable to bind socket at %pI4:%u, "
-                    "ret=%d\n", &addr, ntohs(port), ret);
+               printk(KERN_ERR "o2net: Error %d while binding socket at "
+                      "%pI4:%u\n", ret, &addr, ntohs(port)); 
                goto out;
        }
 
        ret = sock->ops->listen(sock, 64);
-       if (ret < 0) {
-               mlog(ML_ERROR, "unable to listen on %pI4:%u, ret=%d\n",
-                    &addr, ntohs(port), ret);
-       }
+       if (ret < 0)
+               printk(KERN_ERR "o2net: Error %d while listening on %pI4:%u\n",
+                      ret, &addr, ntohs(port));
 
 out:
        if (ret) {
index fd6179e..5bada2a 100644 (file)
@@ -106,6 +106,8 @@ int o2net_register_handler(u32 msg_type, u32 key, u32 max_len,
                           struct list_head *unreg_list);
 void o2net_unregister_handler_list(struct list_head *list);
 
+void o2net_fill_node_map(unsigned long *map, unsigned bytes);
+
 struct o2nm_node;
 int o2net_register_hb_callbacks(void);
 void o2net_unregister_hb_callbacks(void);
index e2878b5..8fe4e28 100644 (file)
@@ -1184,8 +1184,7 @@ static int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
                        if (pde)
                                le16_add_cpu(&pde->rec_len,
                                                le16_to_cpu(de->rec_len));
-                       else
-                               de->inode = 0;
+                       de->inode = 0;
                        dir->i_version++;
                        ocfs2_journal_dirty(handle, bh);
                        goto bail;
index d602abb..a5952ce 100644 (file)
@@ -859,8 +859,8 @@ void dlm_complete_recovery_thread(struct dlm_ctxt *dlm);
 void dlm_wait_for_recovery(struct dlm_ctxt *dlm);
 void dlm_kick_recovery_thread(struct dlm_ctxt *dlm);
 int dlm_is_node_dead(struct dlm_ctxt *dlm, u8 node);
-int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout);
-int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout);
+void dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout);
+void dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout);
 
 void dlm_put(struct dlm_ctxt *dlm);
 struct dlm_ctxt *dlm_grab(struct dlm_ctxt *dlm);
@@ -877,9 +877,8 @@ static inline void dlm_lockres_get(struct dlm_lock_resource *res)
        kref_get(&res->refs);
 }
 void dlm_lockres_put(struct dlm_lock_resource *res);
-void __dlm_unhash_lockres(struct dlm_lock_resource *res);
-void __dlm_insert_lockres(struct dlm_ctxt *dlm,
-                         struct dlm_lock_resource *res);
+void __dlm_unhash_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
+void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res);
 struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
                                                     const char *name,
                                                     unsigned int len,
@@ -902,46 +901,15 @@ struct dlm_lock_resource *dlm_new_lockres(struct dlm_ctxt *dlm,
                                          const char *name,
                                          unsigned int namelen);
 
-#define dlm_lockres_set_refmap_bit(bit,res)  \
-       __dlm_lockres_set_refmap_bit(bit,res,__FILE__,__LINE__)
-#define dlm_lockres_clear_refmap_bit(bit,res)  \
-       __dlm_lockres_clear_refmap_bit(bit,res,__FILE__,__LINE__)
+void dlm_lockres_set_refmap_bit(struct dlm_ctxt *dlm,
+                               struct dlm_lock_resource *res, int bit);
+void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm,
+                                 struct dlm_lock_resource *res, int bit);
 
-static inline void __dlm_lockres_set_refmap_bit(int bit,
-                                               struct dlm_lock_resource *res,
-                                               const char *file,
-                                               int line)
-{
-       //printk("%s:%d:%.*s: setting bit %d\n", file, line,
-       //     res->lockname.len, res->lockname.name, bit);
-       set_bit(bit, res->refmap);
-}
-
-static inline void __dlm_lockres_clear_refmap_bit(int bit,
-                                                 struct dlm_lock_resource *res,
-                                                 const char *file,
-                                                 int line)
-{
-       //printk("%s:%d:%.*s: clearing bit %d\n", file, line,
-       //     res->lockname.len, res->lockname.name, bit);
-       clear_bit(bit, res->refmap);
-}
-
-void __dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
-                                  struct dlm_lock_resource *res,
-                                  const char *file,
-                                  int line);
-void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
-                                  struct dlm_lock_resource *res,
-                                  int new_lockres,
-                                  const char *file,
-                                  int line);
-#define dlm_lockres_drop_inflight_ref(d,r)  \
-       __dlm_lockres_drop_inflight_ref(d,r,__FILE__,__LINE__)
-#define dlm_lockres_grab_inflight_ref(d,r)  \
-       __dlm_lockres_grab_inflight_ref(d,r,0,__FILE__,__LINE__)
-#define dlm_lockres_grab_inflight_ref_new(d,r)  \
-       __dlm_lockres_grab_inflight_ref(d,r,1,__FILE__,__LINE__)
+void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
+                                  struct dlm_lock_resource *res);
+void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
+                                  struct dlm_lock_resource *res);
 
 void dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
 void dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock);
index 6ed6b95..92f2ead 100644 (file)
@@ -157,16 +157,18 @@ static int dlm_protocol_compare(struct dlm_protocol_version *existing,
 
 static void dlm_unregister_domain_handlers(struct dlm_ctxt *dlm);
 
-void __dlm_unhash_lockres(struct dlm_lock_resource *lockres)
+void __dlm_unhash_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
 {
-       if (!hlist_unhashed(&lockres->hash_node)) {
-               hlist_del_init(&lockres->hash_node);
-               dlm_lockres_put(lockres);
-       }
+       if (hlist_unhashed(&res->hash_node))
+               return;
+
+       mlog(0, "%s: Unhash res %.*s\n", dlm->name, res->lockname.len,
+            res->lockname.name);
+       hlist_del_init(&res->hash_node);
+       dlm_lockres_put(res);
 }
 
-void __dlm_insert_lockres(struct dlm_ctxt *dlm,
-                      struct dlm_lock_resource *res)
+void __dlm_insert_lockres(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
 {
        struct hlist_head *bucket;
        struct qstr *q;
@@ -180,6 +182,9 @@ void __dlm_insert_lockres(struct dlm_ctxt *dlm,
        dlm_lockres_get(res);
 
        hlist_add_head(&res->hash_node, bucket);
+
+       mlog(0, "%s: Hash res %.*s\n", dlm->name, res->lockname.len,
+            res->lockname.name);
 }
 
 struct dlm_lock_resource * __dlm_lookup_lockres_full(struct dlm_ctxt *dlm,
@@ -539,17 +544,17 @@ again:
 
 static void __dlm_print_nodes(struct dlm_ctxt *dlm)
 {
-       int node = -1;
+       int node = -1, num = 0;
 
        assert_spin_locked(&dlm->spinlock);
 
-       printk(KERN_NOTICE "o2dlm: Nodes in domain %s: ", dlm->name);
-
+       printk("( ");
        while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES,
                                     node + 1)) < O2NM_MAX_NODES) {
                printk("%d ", node);
+               ++num;
        }
-       printk("\n");
+       printk(") %u nodes\n", num);
 }
 
 static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
@@ -566,11 +571,10 @@ static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,
 
        node = exit_msg->node_idx;
 
-       printk(KERN_NOTICE "o2dlm: Node %u leaves domain %s\n", node, dlm->name);
-
        spin_lock(&dlm->spinlock);
        clear_bit(node, dlm->domain_map);
        clear_bit(node, dlm->exit_domain_map);
+       printk(KERN_NOTICE "o2dlm: Node %u leaves domain %s ", node, dlm->name);
        __dlm_print_nodes(dlm);
 
        /* notify anything attached to the heartbeat events */
@@ -755,6 +759,7 @@ void dlm_unregister_domain(struct dlm_ctxt *dlm)
 
                dlm_mark_domain_leaving(dlm);
                dlm_leave_domain(dlm);
+               printk(KERN_NOTICE "o2dlm: Leaving domain %s\n", dlm->name);
                dlm_force_free_mles(dlm);
                dlm_complete_dlm_shutdown(dlm);
        }
@@ -970,7 +975,7 @@ static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,
                clear_bit(assert->node_idx, dlm->exit_domain_map);
                __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
 
-               printk(KERN_NOTICE "o2dlm: Node %u joins domain %s\n",
+               printk(KERN_NOTICE "o2dlm: Node %u joins domain %s ",
                       assert->node_idx, dlm->name);
                __dlm_print_nodes(dlm);
 
@@ -1701,8 +1706,10 @@ static int dlm_try_to_join_domain(struct dlm_ctxt *dlm)
 bail:
        spin_lock(&dlm->spinlock);
        __dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);
-       if (!status)
+       if (!status) {
+               printk(KERN_NOTICE "o2dlm: Joining domain %s ", dlm->name);
                __dlm_print_nodes(dlm);
+       }
        spin_unlock(&dlm->spinlock);
 
        if (ctxt) {
@@ -2131,13 +2138,6 @@ struct dlm_ctxt * dlm_register_domain(const char *domain,
                goto leave;
        }
 
-       if (!o2hb_check_local_node_heartbeating()) {
-               mlog(ML_ERROR, "the local node has not been configured, or is "
-                    "not heartbeating\n");
-               ret = -EPROTO;
-               goto leave;
-       }
-
        mlog(0, "register called for domain \"%s\"\n", domain);
 
 retry:
index 8d39e0f..975810b 100644 (file)
@@ -183,10 +183,6 @@ static enum dlm_status dlmlock_master(struct dlm_ctxt *dlm,
                        kick_thread = 1;
                }
        }
-       /* reduce the inflight count, this may result in the lockres
-        * being purged below during calc_usage */
-       if (lock->ml.node == dlm->node_num)
-               dlm_lockres_drop_inflight_ref(dlm, res);
 
        spin_unlock(&res->spinlock);
        wake_up(&res->wq);
@@ -231,10 +227,16 @@ static enum dlm_status dlmlock_remote(struct dlm_ctxt *dlm,
             lock->ml.type, res->lockname.len,
             res->lockname.name, flags);
 
+       /*
+        * Wait if resource is getting recovered, remastered, etc.
+        * If the resource was remastered and new owner is self, then exit.
+        */
        spin_lock(&res->spinlock);
-
-       /* will exit this call with spinlock held */
        __dlm_wait_on_lockres(res);
+       if (res->owner == dlm->node_num) {
+               spin_unlock(&res->spinlock);
+               return DLM_RECOVERING;
+       }
        res->state |= DLM_LOCK_RES_IN_PROGRESS;
 
        /* add lock to local (secondary) queue */
@@ -319,27 +321,23 @@ static enum dlm_status dlm_send_remote_lock_request(struct dlm_ctxt *dlm,
        tmpret = o2net_send_message(DLM_CREATE_LOCK_MSG, dlm->key, &create,
                                    sizeof(create), res->owner, &status);
        if (tmpret >= 0) {
-               // successfully sent and received
-               ret = status;  // this is already a dlm_status
+               ret = status;
                if (ret == DLM_REJECTED) {
-                       mlog(ML_ERROR, "%s:%.*s: BUG.  this is a stale lockres "
-                            "no longer owned by %u.  that node is coming back "
-                            "up currently.\n", dlm->name, create.namelen,
+                       mlog(ML_ERROR, "%s: res %.*s, Stale lockres no longer "
+                            "owned by node %u. That node is coming back up "
+                            "currently.\n", dlm->name, create.namelen,
                             create.name, res->owner);
                        dlm_print_one_lock_resource(res);
                        BUG();
                }
        } else {
-               mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to "
-                    "node %u\n", tmpret, DLM_CREATE_LOCK_MSG, dlm->key,
-                    res->owner);
-               if (dlm_is_host_down(tmpret)) {
+               mlog(ML_ERROR, "%s: res %.*s, Error %d send CREATE LOCK to "
+                    "node %u\n", dlm->name, create.namelen, create.name,
+                    tmpret, res->owner);
+               if (dlm_is_host_down(tmpret))
                        ret = DLM_RECOVERING;
-                       mlog(0, "node %u died so returning DLM_RECOVERING "
-                            "from lock message!\n", res->owner);
-               } else {
+               else
                        ret = dlm_err_to_dlm_status(tmpret);
-               }
        }
 
        return ret;
@@ -440,7 +438,7 @@ struct dlm_lock * dlm_new_lock(int type, u8 node, u64 cookie,
                /* zero memory only if kernel-allocated */
                lksb = kzalloc(sizeof(*lksb), GFP_NOFS);
                if (!lksb) {
-                       kfree(lock);
+                       kmem_cache_free(dlm_lock_cache, lock);
                        return NULL;
                }
                kernel_allocated = 1;
@@ -718,18 +716,10 @@ retry_lock:
 
                if (status == DLM_RECOVERING || status == DLM_MIGRATING ||
                    status == DLM_FORWARD) {
-                       mlog(0, "retrying lock with migration/"
-                            "recovery/in progress\n");
                        msleep(100);
-                       /* no waiting for dlm_reco_thread */
                        if (recovery) {
                                if (status != DLM_RECOVERING)
                                        goto retry_lock;
-
-                               mlog(0, "%s: got RECOVERING "
-                                    "for $RECOVERY lock, master "
-                                    "was %u\n", dlm->name,
-                                    res->owner);
                                /* wait to see the node go down, then
                                 * drop down and allow the lockres to
                                 * get cleaned up.  need to remaster. */
@@ -741,6 +731,14 @@ retry_lock:
                        }
                }
 
+               /* Inflight taken in dlm_get_lock_resource() is dropped here */
+               spin_lock(&res->spinlock);
+               dlm_lockres_drop_inflight_ref(dlm, res);
+               spin_unlock(&res->spinlock);
+
+               dlm_lockres_calc_usage(dlm, res);
+               dlm_kick_thread(dlm, res);
+
                if (status != DLM_NORMAL) {
                        lock->lksb->flags &= ~DLM_LKSB_GET_LVB;
                        if (status != DLM_NOTQUEUED)
index 11eefb8..005261c 100644 (file)
@@ -631,39 +631,54 @@ error:
        return NULL;
 }
 
-void __dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
-                                  struct dlm_lock_resource *res,
-                                  int new_lockres,
-                                  const char *file,
-                                  int line)
+void dlm_lockres_set_refmap_bit(struct dlm_ctxt *dlm,
+                               struct dlm_lock_resource *res, int bit)
 {
-       if (!new_lockres)
-               assert_spin_locked(&res->spinlock);
+       assert_spin_locked(&res->spinlock);
+
+       mlog(0, "res %.*s, set node %u, %ps()\n", res->lockname.len,
+            res->lockname.name, bit, __builtin_return_address(0));
+
+       set_bit(bit, res->refmap);
+}
+
+void dlm_lockres_clear_refmap_bit(struct dlm_ctxt *dlm,
+                                 struct dlm_lock_resource *res, int bit)
+{
+       assert_spin_locked(&res->spinlock);
+
+       mlog(0, "res %.*s, clr node %u, %ps()\n", res->lockname.len,
+            res->lockname.name, bit, __builtin_return_address(0));
+
+       clear_bit(bit, res->refmap);
+}
+
+
+void dlm_lockres_grab_inflight_ref(struct dlm_ctxt *dlm,
+                                  struct dlm_lock_resource *res)
+{
+       assert_spin_locked(&res->spinlock);
 
-       if (!test_bit(dlm->node_num, res->refmap)) {
-               BUG_ON(res->inflight_locks != 0);
-               dlm_lockres_set_refmap_bit(dlm->node_num, res);
-       }
        res->inflight_locks++;
-       mlog(0, "%s:%.*s: inflight++: now %u\n",
-            dlm->name, res->lockname.len, res->lockname.name,
-            res->inflight_locks);
+
+       mlog(0, "%s: res %.*s, inflight++: now %u, %ps()\n", dlm->name,
+            res->lockname.len, res->lockname.name, res->inflight_locks,
+            __builtin_return_address(0));
 }
 
-void __dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
-                                  struct dlm_lock_resource *res,
-                                  const char *file,
-                                  int line)
+void dlm_lockres_drop_inflight_ref(struct dlm_ctxt *dlm,
+                                  struct dlm_lock_resource *res)
 {
        assert_spin_locked(&res->spinlock);
 
        BUG_ON(res->inflight_locks == 0);
+
        res->inflight_locks--;
-       mlog(0, "%s:%.*s: inflight--: now %u\n",
-            dlm->name, res->lockname.len, res->lockname.name,
-            res->inflight_locks);
-       if (res->inflight_locks == 0)
-               dlm_lockres_clear_refmap_bit(dlm->node_num, res);
+
+       mlog(0, "%s: res %.*s, inflight--: now %u, %ps()\n", dlm->name,
+            res->lockname.len, res->lockname.name, res->inflight_locks,
+            __builtin_return_address(0));
+
        wake_up(&res->wq);
 }
 
@@ -697,7 +712,6 @@ struct dlm_lock_resource * dlm_get_lock_resource(struct dlm_ctxt *dlm,
        unsigned int hash;
        int tries = 0;
        int bit, wait_on_recovery = 0;
-       int drop_inflight_if_nonlocal = 0;
 
        BUG_ON(!lockid);
 
@@ -709,36 +723,33 @@ lookup:
        spin_lock(&dlm->spinlock);
        tmpres = __dlm_lookup_lockres_full(dlm, lockid, namelen, hash);
        if (tmpres) {
-               int dropping_ref = 0;
-
                spin_unlock(&dlm->spinlock);
-
                spin_lock(&tmpres->spinlock);
-               /* We wait for the other thread that is mastering the resource */
+               /* Wait on the thread that is mastering the resource */
                if (tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN) {
                        __dlm_wait_on_lockres(tmpres);
                        BUG_ON(tmpres->owner == DLM_LOCK_RES_OWNER_UNKNOWN);
+                       spin_unlock(&tmpres->spinlock);
+                       dlm_lockres_put(tmpres);
+                       tmpres = NULL;
+                       goto lookup;
                }
 
-               if (tmpres->owner == dlm->node_num) {
-                       BUG_ON(tmpres->state & DLM_LOCK_RES_DROPPING_REF);
-                       dlm_lockres_grab_inflight_ref(dlm, tmpres);
-               } else if (tmpres->state & DLM_LOCK_RES_DROPPING_REF)
-                       dropping_ref = 1;
-               spin_unlock(&tmpres->spinlock);
-
-               /* wait until done messaging the master, drop our ref to allow
-                * the lockres to be purged, start over. */
-               if (dropping_ref) {
-                       spin_lock(&tmpres->spinlock);
-                       __dlm_wait_on_lockres_flags(tmpres, DLM_LOCK_RES_DROPPING_REF);
+               /* Wait on the resource purge to complete before continuing */
+               if (tmpres->state & DLM_LOCK_RES_DROPPING_REF) {
+                       BUG_ON(tmpres->owner == dlm->node_num);
+                       __dlm_wait_on_lockres_flags(tmpres,
+                                                   DLM_LOCK_RES_DROPPING_REF);
                        spin_unlock(&tmpres->spinlock);
                        dlm_lockres_put(tmpres);
                        tmpres = NULL;
                        goto lookup;
                }
 
-               mlog(0, "found in hash!\n");
+               /* Grab inflight ref to pin the resource */
+               dlm_lockres_grab_inflight_ref(dlm, tmpres);
+
+               spin_unlock(&tmpres->spinlock);
                if (res)
                        dlm_lockres_put(res);
                res = tmpres;
@@ -829,8 +840,8 @@ lookup:
                 * but they might own this lockres.  wait on them. */
                bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0);
                if (bit < O2NM_MAX_NODES) {
-                       mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to "
-                            "recover before lock mastery can begin\n",
+                       mlog(0, "%s: res %.*s, At least one node (%d) "
+                            "to recover before lock mastery can begin\n",
                             dlm->name, namelen, (char *)lockid, bit);
                        wait_on_recovery = 1;
                }
@@ -843,12 +854,11 @@ lookup:
 
        /* finally add the lockres to its hash bucket */
        __dlm_insert_lockres(dlm, res);
-       /* since this lockres is new it doesn't not require the spinlock */
-       dlm_lockres_grab_inflight_ref_new(dlm, res);
 
-       /* if this node does not become the master make sure to drop
-        * this inflight reference below */
-       drop_inflight_if_nonlocal = 1;
+       /* Grab inflight ref to pin the resource */
+       spin_lock(&res->spinlock);
+       dlm_lockres_grab_inflight_ref(dlm, res);
+       spin_unlock(&res->spinlock);
 
        /* get an extra ref on the mle in case this is a BLOCK
         * if so, the creator of the BLOCK may try to put the last
@@ -864,8 +874,8 @@ redo_request:
                 * dlm spinlock would be detectable be a change on the mle,
                 * so we only need to clear out the recovery map once. */
                if (dlm_is_recovery_lock(lockid, namelen)) {
-                       mlog(ML_NOTICE, "%s: recovery map is not empty, but "
-                            "must master $RECOVERY lock now\n", dlm->name);
+                       mlog(0, "%s: Recovery map is not empty, but must "
+                            "master $RECOVERY lock now\n", dlm->name);
                        if (!dlm_pre_master_reco_lockres(dlm, res))
                                wait_on_recovery = 0;
                        else {
@@ -883,8 +893,8 @@ redo_request:
                spin_lock(&dlm->spinlock);
                bit = find_next_bit(dlm->recovery_map, O2NM_MAX_NODES, 0);
                if (bit < O2NM_MAX_NODES) {
-                       mlog(ML_NOTICE, "%s:%.*s: at least one node (%d) to "
-                            "recover before lock mastery can begin\n",
+                       mlog(0, "%s: res %.*s, At least one node (%d) "
+                            "to recover before lock mastery can begin\n",
                             dlm->name, namelen, (char *)lockid, bit);
                        wait_on_recovery = 1;
                } else
@@ -913,8 +923,8 @@ redo_request:
                         * yet, keep going until it does.  this is how the
                         * master will know that asserts are needed back to
                         * the lower nodes. */
-                       mlog(0, "%s:%.*s: requests only up to %u but master "
-                            "is %u, keep going\n", dlm->name, namelen,
+                       mlog(0, "%s: res %.*s, Requests only up to %u but "
+                            "master is %u, keep going\n", dlm->name, namelen,
                             lockid, nodenum, mle->master);
                }
        }
@@ -924,13 +934,12 @@ wait:
        ret = dlm_wait_for_lock_mastery(dlm, res, mle, &blocked);
        if (ret < 0) {
                wait_on_recovery = 1;
-               mlog(0, "%s:%.*s: node map changed, redo the "
-                    "master request now, blocked=%d\n",
-                    dlm->name, res->lockname.len,
+               mlog(0, "%s: res %.*s, Node map changed, redo the master "
+                    "request now, blocked=%d\n", dlm->name, res->lockname.len,
                     res->lockname.name, blocked);
                if (++tries > 20) {
-                       mlog(ML_ERROR, "%s:%.*s: spinning on "
-                            "dlm_wait_for_lock_mastery, blocked=%d\n",
+                       mlog(ML_ERROR, "%s: res %.*s, Spinning on "
+                            "dlm_wait_for_lock_mastery, blocked = %d\n",
                             dlm->name, res->lockname.len,
                             res->lockname.name, blocked);
                        dlm_print_one_lock_resource(res);
@@ -940,7 +949,8 @@ wait:
                goto redo_request;
        }
 
-       mlog(0, "lockres mastered by %u\n", res->owner);
+       mlog(0, "%s: res %.*s, Mastered by %u\n", dlm->name, res->lockname.len,
+            res->lockname.name, res->owner);
        /* make sure we never continue without this */
        BUG_ON(res->owner == O2NM_MAX_NODES);
 
@@ -952,8 +962,6 @@ wait:
 
 wake_waiters:
        spin_lock(&res->spinlock);
-       if (res->owner != dlm->node_num && drop_inflight_if_nonlocal)
-               dlm_lockres_drop_inflight_ref(dlm, res);
        res->state &= ~DLM_LOCK_RES_IN_PROGRESS;
        spin_unlock(&res->spinlock);
        wake_up(&res->wq);
@@ -1426,9 +1434,7 @@ way_up_top:
                }
 
                if (res->owner == dlm->node_num) {
-                       mlog(0, "%s:%.*s: setting bit %u in refmap\n",
-                            dlm->name, namelen, name, request->node_idx);
-                       dlm_lockres_set_refmap_bit(request->node_idx, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, request->node_idx);
                        spin_unlock(&res->spinlock);
                        response = DLM_MASTER_RESP_YES;
                        if (mle)
@@ -1493,10 +1499,8 @@ way_up_top:
                                 * go back and clean the mles on any
                                 * other nodes */
                                dispatch_assert = 1;
-                               dlm_lockres_set_refmap_bit(request->node_idx, res);
-                               mlog(0, "%s:%.*s: setting bit %u in refmap\n",
-                                    dlm->name, namelen, name,
-                                    request->node_idx);
+                               dlm_lockres_set_refmap_bit(dlm, res,
+                                                          request->node_idx);
                        } else
                                response = DLM_MASTER_RESP_NO;
                } else {
@@ -1702,7 +1706,7 @@ again:
                             "lockres, set the bit in the refmap\n",
                             namelen, lockname, to);
                        spin_lock(&res->spinlock);
-                       dlm_lockres_set_refmap_bit(to, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, to);
                        spin_unlock(&res->spinlock);
                }
        }
@@ -2187,8 +2191,6 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
        namelen = res->lockname.len;
        BUG_ON(namelen > O2NM_MAX_NAME_LEN);
 
-       mlog(0, "%s:%.*s: sending deref to %d\n",
-            dlm->name, namelen, lockname, res->owner);
        memset(&deref, 0, sizeof(deref));
        deref.node_idx = dlm->node_num;
        deref.namelen = namelen;
@@ -2197,14 +2199,12 @@ int dlm_drop_lockres_ref(struct dlm_ctxt *dlm, struct dlm_lock_resource *res)
        ret = o2net_send_message(DLM_DEREF_LOCKRES_MSG, dlm->key,
                                 &deref, sizeof(deref), res->owner, &r);
        if (ret < 0)
-               mlog(ML_ERROR, "Error %d when sending message %u (key 0x%x) to "
-                    "node %u\n", ret, DLM_DEREF_LOCKRES_MSG, dlm->key,
-                    res->owner);
+               mlog(ML_ERROR, "%s: res %.*s, error %d send DEREF to node %u\n",
+                    dlm->name, namelen, lockname, ret, res->owner);
        else if (r < 0) {
                /* BAD.  other node says I did not have a ref. */
-               mlog(ML_ERROR,"while dropping ref on %s:%.*s "
-                   "(master=%u) got %d.\n", dlm->name, namelen,
-                   lockname, res->owner, r);
+               mlog(ML_ERROR, "%s: res %.*s, DEREF to node %u got %d\n",
+                    dlm->name, namelen, lockname, res->owner, r);
                dlm_print_one_lock_resource(res);
                BUG();
        }
@@ -2260,7 +2260,7 @@ int dlm_deref_lockres_handler(struct o2net_msg *msg, u32 len, void *data,
        else {
                BUG_ON(res->state & DLM_LOCK_RES_DROPPING_REF);
                if (test_bit(node, res->refmap)) {
-                       dlm_lockres_clear_refmap_bit(node, res);
+                       dlm_lockres_clear_refmap_bit(dlm, res, node);
                        cleared = 1;
                }
        }
@@ -2320,7 +2320,7 @@ static void dlm_deref_lockres_worker(struct dlm_work_item *item, void *data)
        BUG_ON(res->state & DLM_LOCK_RES_DROPPING_REF);
        if (test_bit(node, res->refmap)) {
                __dlm_wait_on_lockres_flags(res, DLM_LOCK_RES_SETREF_INPROG);
-               dlm_lockres_clear_refmap_bit(node, res);
+               dlm_lockres_clear_refmap_bit(dlm, res, node);
                cleared = 1;
        }
        spin_unlock(&res->spinlock);
@@ -2802,7 +2802,8 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
                                BUG_ON(!list_empty(&lock->bast_list));
                                BUG_ON(lock->ast_pending);
                                BUG_ON(lock->bast_pending);
-                               dlm_lockres_clear_refmap_bit(lock->ml.node, res);
+                               dlm_lockres_clear_refmap_bit(dlm, res,
+                                                            lock->ml.node);
                                list_del_init(&lock->list);
                                dlm_lock_put(lock);
                                /* In a normal unlock, we would have added a
@@ -2823,7 +2824,7 @@ static void dlm_remove_nonlocal_locks(struct dlm_ctxt *dlm,
                        mlog(0, "%s:%.*s: node %u had a ref to this "
                             "migrating lockres, clearing\n", dlm->name,
                             res->lockname.len, res->lockname.name, bit);
-                       dlm_lockres_clear_refmap_bit(bit, res);
+                       dlm_lockres_clear_refmap_bit(dlm, res, bit);
                }
                bit++;
        }
@@ -2916,9 +2917,9 @@ static int dlm_do_migrate_request(struct dlm_ctxt *dlm,
                                         &migrate, sizeof(migrate), nodenum,
                                         &status);
                if (ret < 0) {
-                       mlog(ML_ERROR, "Error %d when sending message %u (key "
-                            "0x%x) to node %u\n", ret, DLM_MIGRATE_REQUEST_MSG,
-                            dlm->key, nodenum);
+                       mlog(ML_ERROR, "%s: res %.*s, Error %d send "
+                            "MIGRATE_REQUEST to node %u\n", dlm->name,
+                            migrate.namelen, migrate.name, ret, nodenum);
                        if (!dlm_is_host_down(ret)) {
                                mlog(ML_ERROR, "unhandled error=%d!\n", ret);
                                BUG();
@@ -2937,7 +2938,7 @@ static int dlm_do_migrate_request(struct dlm_ctxt *dlm,
                             dlm->name, res->lockname.len, res->lockname.name,
                             nodenum);
                        spin_lock(&res->spinlock);
-                       dlm_lockres_set_refmap_bit(nodenum, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, nodenum);
                        spin_unlock(&res->spinlock);
                }
        }
@@ -3271,7 +3272,7 @@ int dlm_finish_migration(struct dlm_ctxt *dlm, struct dlm_lock_resource *res,
         * mastery reference here since old_master will briefly have
         * a reference after the migration completes */
        spin_lock(&res->spinlock);
-       dlm_lockres_set_refmap_bit(old_master, res);
+       dlm_lockres_set_refmap_bit(dlm, res, old_master);
        spin_unlock(&res->spinlock);
 
        mlog(0, "now time to do a migrate request to other nodes\n");
index 7efab6d..01ebfd0 100644 (file)
@@ -362,40 +362,38 @@ static int dlm_is_node_recovered(struct dlm_ctxt *dlm, u8 node)
 }
 
 
-int dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout)
+void dlm_wait_for_node_death(struct dlm_ctxt *dlm, u8 node, int timeout)
 {
-       if (timeout) {
-               mlog(ML_NOTICE, "%s: waiting %dms for notification of "
-                    "death of node %u\n", dlm->name, timeout, node);
+       if (dlm_is_node_dead(dlm, node))
+               return;
+
+       printk(KERN_NOTICE "o2dlm: Waiting on the death of node %u in "
+              "domain %s\n", node, dlm->name);
+
+       if (timeout)
                wait_event_timeout(dlm->dlm_reco_thread_wq,
-                          dlm_is_node_dead(dlm, node),
-                          msecs_to_jiffies(timeout));
-       } else {
-               mlog(ML_NOTICE, "%s: waiting indefinitely for notification "
-                    "of death of node %u\n", dlm->name, node);
+                                  dlm_is_node_dead(dlm, node),
+                                  msecs_to_jiffies(timeout));
+       else
                wait_event(dlm->dlm_reco_thread_wq,
                           dlm_is_node_dead(dlm, node));
-       }
-       /* for now, return 0 */
-       return 0;
 }
 
-int dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout)
+void dlm_wait_for_node_recovery(struct dlm_ctxt *dlm, u8 node, int timeout)
 {
-       if (timeout) {
-               mlog(0, "%s: waiting %dms for notification of "
-                    "recovery of node %u\n", dlm->name, timeout, node);
+       if (dlm_is_node_recovered(dlm, node))
+               return;
+
+       printk(KERN_NOTICE "o2dlm: Waiting on the recovery of node %u in "
+              "domain %s\n", node, dlm->name);
+
+       if (timeout)
                wait_event_timeout(dlm->dlm_reco_thread_wq,
-                          dlm_is_node_recovered(dlm, node),
-                          msecs_to_jiffies(timeout));
-       } else {
-               mlog(0, "%s: waiting indefinitely for notification "
-                    "of recovery of node %u\n", dlm->name, node);
+                                  dlm_is_node_recovered(dlm, node),
+                                  msecs_to_jiffies(timeout));
+       else
                wait_event(dlm->dlm_reco_thread_wq,
                           dlm_is_node_recovered(dlm, node));
-       }
-       /* for now, return 0 */
-       return 0;
 }
 
 /* callers of the top-level api calls (dlmlock/dlmunlock) should
@@ -430,6 +428,8 @@ static void dlm_begin_recovery(struct dlm_ctxt *dlm)
 {
        spin_lock(&dlm->spinlock);
        BUG_ON(dlm->reco.state & DLM_RECO_STATE_ACTIVE);
+       printk(KERN_NOTICE "o2dlm: Begin recovery on domain %s for node %u\n",
+              dlm->name, dlm->reco.dead_node);
        dlm->reco.state |= DLM_RECO_STATE_ACTIVE;
        spin_unlock(&dlm->spinlock);
 }
@@ -440,9 +440,18 @@ static void dlm_end_recovery(struct dlm_ctxt *dlm)
        BUG_ON(!(dlm->reco.state & DLM_RECO_STATE_ACTIVE));
        dlm->reco.state &= ~DLM_RECO_STATE_ACTIVE;
        spin_unlock(&dlm->spinlock);
+       printk(KERN_NOTICE "o2dlm: End recovery on domain %s\n", dlm->name);
        wake_up(&dlm->reco.event);
 }
 
+static void dlm_print_recovery_master(struct dlm_ctxt *dlm)
+{
+       printk(KERN_NOTICE "o2dlm: Node %u (%s) is the Recovery Master for the "
+              "dead node %u in domain %s\n", dlm->reco.new_master,
+              (dlm->node_num == dlm->reco.new_master ? "me" : "he"),
+              dlm->reco.dead_node, dlm->name);
+}
+
 static int dlm_do_recovery(struct dlm_ctxt *dlm)
 {
        int status = 0;
@@ -505,9 +514,8 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
                }
                mlog(0, "another node will master this recovery session.\n");
        }
-       mlog(0, "dlm=%s (%d), new_master=%u, this node=%u, dead_node=%u\n",
-            dlm->name, task_pid_nr(dlm->dlm_reco_thread_task), dlm->reco.new_master,
-            dlm->node_num, dlm->reco.dead_node);
+
+       dlm_print_recovery_master(dlm);
 
        /* it is safe to start everything back up here
         * because all of the dead node's lock resources
@@ -518,15 +526,13 @@ static int dlm_do_recovery(struct dlm_ctxt *dlm)
        return 0;
 
 master_here:
-       mlog(ML_NOTICE, "(%d) Node %u is the Recovery Master for the Dead Node "
-            "%u for Domain %s\n", task_pid_nr(dlm->dlm_reco_thread_task),
-            dlm->node_num, dlm->reco.dead_node, dlm->name);
+       dlm_print_recovery_master(dlm);
 
        status = dlm_remaster_locks(dlm, dlm->reco.dead_node);
        if (status < 0) {
                /* we should never hit this anymore */
-               mlog(ML_ERROR, "error %d remastering locks for node %u, "
-                    "retrying.\n", status, dlm->reco.dead_node);
+               mlog(ML_ERROR, "%s: Error %d remastering locks for node %u, "
+                    "retrying.\n", dlm->name, status, dlm->reco.dead_node);
                /* yield a bit to allow any final network messages
                 * to get handled on remaining nodes */
                msleep(100);
@@ -567,7 +573,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
                BUG_ON(ndata->state != DLM_RECO_NODE_DATA_INIT);
                ndata->state = DLM_RECO_NODE_DATA_REQUESTING;
 
-               mlog(0, "requesting lock info from node %u\n",
+               mlog(0, "%s: Requesting lock info from node %u\n", dlm->name,
                     ndata->node_num);
 
                if (ndata->node_num == dlm->node_num) {
@@ -640,7 +646,7 @@ static int dlm_remaster_locks(struct dlm_ctxt *dlm, u8 dead_node)
                spin_unlock(&dlm_reco_state_lock);
        }
 
-       mlog(0, "done requesting all lock info\n");
+       mlog(0, "%s: Done requesting all lock info\n", dlm->name);
 
        /* nodes should be sending reco data now
         * just need to wait */
@@ -802,10 +808,9 @@ static int dlm_request_all_locks(struct dlm_ctxt *dlm, u8 request_from,
 
        /* negative status is handled by caller */
        if (ret < 0)
-               mlog(ML_ERROR, "Error %d when sending message %u (key "
-                    "0x%x) to node %u\n", ret, DLM_LOCK_REQUEST_MSG,
-                    dlm->key, request_from);
-
+               mlog(ML_ERROR, "%s: Error %d send LOCK_REQUEST to node %u "
+                    "to recover dead node %u\n", dlm->name, ret,
+                    request_from, dead_node);
        // return from here, then
        // sleep until all received or error
        return ret;
@@ -956,9 +961,9 @@ static int dlm_send_all_done_msg(struct dlm_ctxt *dlm, u8 dead_node, u8 send_to)
        ret = o2net_send_message(DLM_RECO_DATA_DONE_MSG, dlm->key, &done_msg,
                                 sizeof(done_msg), send_to, &tmpret);
        if (ret < 0) {
-               mlog(ML_ERROR, "Error %d when sending message %u (key "
-                    "0x%x) to node %u\n", ret, DLM_RECO_DATA_DONE_MSG,
-                    dlm->key, send_to);
+               mlog(ML_ERROR, "%s: Error %d send RECO_DATA_DONE to node %u "
+                    "to recover dead node %u\n", dlm->name, ret, send_to,
+                    dead_node);
                if (!dlm_is_host_down(ret)) {
                        BUG();
                }
@@ -1127,9 +1132,11 @@ static int dlm_send_mig_lockres_msg(struct dlm_ctxt *dlm,
        if (ret < 0) {
                /* XXX: negative status is not handled.
                 * this will end up killing this node. */
-               mlog(ML_ERROR, "Error %d when sending message %u (key "
-                    "0x%x) to node %u\n", ret, DLM_MIG_LOCKRES_MSG,
-                    dlm->key, send_to);
+               mlog(ML_ERROR, "%s: res %.*s, Error %d send MIG_LOCKRES to "
+                    "node %u (%s)\n", dlm->name, mres->lockname_len,
+                    mres->lockname, ret, send_to,
+                    (orig_flags & DLM_MRES_MIGRATION ?
+                     "migration" : "recovery"));
        } else {
                /* might get an -ENOMEM back here */
                ret = status;
@@ -1767,7 +1774,7 @@ static int dlm_process_recovery_data(struct dlm_ctxt *dlm,
                             dlm->name, mres->lockname_len, mres->lockname,
                             from);
                        spin_lock(&res->spinlock);
-                       dlm_lockres_set_refmap_bit(from, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, from);
                        spin_unlock(&res->spinlock);
                        added++;
                        break;
@@ -1965,7 +1972,7 @@ skip_lvb:
                        mlog(0, "%s:%.*s: added lock for node %u, "
                             "setting refmap bit\n", dlm->name,
                             res->lockname.len, res->lockname.name, ml->node);
-                       dlm_lockres_set_refmap_bit(ml->node, res);
+                       dlm_lockres_set_refmap_bit(dlm, res, ml->node);
                        added++;
                }
                spin_unlock(&res->spinlock);
@@ -2084,6 +2091,9 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
 
        list_for_each_entry_safe(res, next, &dlm->reco.resources, recovering) {
                if (res->owner == dead_node) {
+                       mlog(0, "%s: res %.*s, Changing owner from %u to %u\n",
+                            dlm->name, res->lockname.len, res->lockname.name,
+                            res->owner, new_master);
                        list_del_init(&res->recovering);
                        spin_lock(&res->spinlock);
                        /* new_master has our reference from
@@ -2105,40 +2115,30 @@ static void dlm_finish_local_lockres_recovery(struct dlm_ctxt *dlm,
        for (i = 0; i < DLM_HASH_BUCKETS; i++) {
                bucket = dlm_lockres_hash(dlm, i);
                hlist_for_each_entry(res, hash_iter, bucket, hash_node) {
-                       if (res->state & DLM_LOCK_RES_RECOVERING) {
-                               if (res->owner == dead_node) {
-                                       mlog(0, "(this=%u) res %.*s owner=%u "
-                                            "was not on recovering list, but "
-                                            "clearing state anyway\n",
-                                            dlm->node_num, res->lockname.len,
-                                            res->lockname.name, new_master);
-                               } else if (res->owner == dlm->node_num) {
-                                       mlog(0, "(this=%u) res %.*s owner=%u "
-                                            "was not on recovering list, "
-                                            "owner is THIS node, clearing\n",
-                                            dlm->node_num, res->lockname.len,
-                                            res->lockname.name, new_master);
-                               } else
-                                       continue;
+                       if (!(res->state & DLM_LOCK_RES_RECOVERING))
+                               continue;
 
-                               if (!list_empty(&res->recovering)) {
-                                       mlog(0, "%s:%.*s: lockres was "
-                                            "marked RECOVERING, owner=%u\n",
-                                            dlm->name, res->lockname.len,
-                                            res->lockname.name, res->owner);
-                                       list_del_init(&res->recovering);
-                                       dlm_lockres_put(res);
-                               }
-                               spin_lock(&res->spinlock);
-                               /* new_master has our reference from
-                                * the lock state sent during recovery */
-                               dlm_change_lockres_owner(dlm, res, new_master);
-                               res->state &= ~DLM_LOCK_RES_RECOVERING;
-                               if (__dlm_lockres_has_locks(res))
-                                       __dlm_dirty_lockres(dlm, res);
-                               spin_unlock(&res->spinlock);
-                               wake_up(&res->wq);
+                       if (res->owner != dead_node &&
+                           res->owner != dlm->node_num)
+                               continue;
+
+                       if (!list_empty(&res->recovering)) {
+                               list_del_init(&res->recovering);
+                               dlm_lockres_put(res);
                        }
+
+                       /* new_master has our reference from
+                        * the lock state sent during recovery */
+                       mlog(0, "%s: res %.*s, Changing owner from %u to %u\n",
+                            dlm->name, res->lockname.len, res->lockname.name,
+                            res->owner, new_master);
+                       spin_lock(&res->spinlock);
+                       dlm_change_lockres_owner(dlm, res, new_master);
+                       res->state &= ~DLM_LOCK_RES_RECOVERING;
+                       if (__dlm_lockres_has_locks(res))
+                               __dlm_dirty_lockres(dlm, res);
+                       spin_unlock(&res->spinlock);
+                       wake_up(&res->wq);
                }
        }
 }
@@ -2252,12 +2252,12 @@ static void dlm_free_dead_locks(struct dlm_ctxt *dlm,
                             res->lockname.len, res->lockname.name, freed, dead_node);
                        __dlm_print_one_lock_resource(res);
                }
-               dlm_lockres_clear_refmap_bit(dead_node, res);
+               dlm_lockres_clear_refmap_bit(dlm, res, dead_node);
        } else if (test_bit(dead_node, res->refmap)) {
                mlog(0, "%s:%.*s: dead node %u had a ref, but had "
                     "no locks and had not purged before dying\n", dlm->name,
                     res->lockname.len, res->lockname.name, dead_node);
-               dlm_lockres_clear_refmap_bit(dead_node, res);
+               dlm_lockres_clear_refmap_bit(dlm, res, dead_node);
        }
 
        /* do not kick thread yet */
@@ -2324,9 +2324,9 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
                        dlm_revalidate_lvb(dlm, res, dead_node);
                        if (res->owner == dead_node) {
                                if (res->state & DLM_LOCK_RES_DROPPING_REF) {
-                                       mlog(ML_NOTICE, "Ignore %.*s for "
+                                       mlog(ML_NOTICE, "%s: res %.*s, Skip "
                                             "recovery as it is being freed\n",
-                                            res->lockname.len,
+                                            dlm->name, res->lockname.len,
                                             res->lockname.name);
                                } else
                                        dlm_move_lockres_to_recovery_list(dlm,
index 1d6d1d2..e73c833 100644 (file)
@@ -94,24 +94,26 @@ int __dlm_lockres_unused(struct dlm_lock_resource *res)
 {
        int bit;
 
+       assert_spin_locked(&res->spinlock);
+
        if (__dlm_lockres_has_locks(res))
                return 0;
 
+       /* Locks are in the process of being created */
+       if (res->inflight_locks)
+               return 0;
+
        if (!list_empty(&res->dirty) || res->state & DLM_LOCK_RES_DIRTY)
                return 0;
 
        if (res->state & DLM_LOCK_RES_RECOVERING)
                return 0;
 
+       /* Another node has this resource with this node as the master */
        bit = find_next_bit(res->refmap, O2NM_MAX_NODES, 0);
        if (bit < O2NM_MAX_NODES)
                return 0;
 
-       /*
-        * since the bit for dlm->node_num is not set, inflight_locks better
-        * be zero
-        */
-       BUG_ON(res->inflight_locks != 0);
        return 1;
 }
 
@@ -185,8 +187,6 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm,
                /* clear our bit from the master's refmap, ignore errors */
                ret = dlm_drop_lockres_ref(dlm, res);
                if (ret < 0) {
-                       mlog(ML_ERROR, "%s: deref %.*s failed %d\n", dlm->name,
-                            res->lockname.len, res->lockname.name, ret);
                        if (!dlm_is_host_down(ret))
                                BUG();
                }
@@ -209,7 +209,7 @@ static void dlm_purge_lockres(struct dlm_ctxt *dlm,
                BUG();
        }
 
-       __dlm_unhash_lockres(res);
+       __dlm_unhash_lockres(dlm, res);
 
        /* lockres is not in the hash now.  drop the flag and wake up
         * any processes waiting in dlm_get_lock_resource. */
index e1ed5e5..81a4cd2 100644 (file)
@@ -1692,7 +1692,7 @@ int ocfs2_open_lock(struct inode *inode)
        mlog(0, "inode %llu take PRMODE open lock\n",
             (unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-       if (ocfs2_mount_local(osb))
+       if (ocfs2_is_hard_readonly(osb) || ocfs2_mount_local(osb))
                goto out;
 
        lockres = &OCFS2_I(inode)->ip_open_lockres;
@@ -1718,6 +1718,12 @@ int ocfs2_try_open_lock(struct inode *inode, int write)
             (unsigned long long)OCFS2_I(inode)->ip_blkno,
             write ? "EXMODE" : "PRMODE");
 
+       if (ocfs2_is_hard_readonly(osb)) {
+               if (write)
+                       status = -EROFS;
+               goto out;
+       }
+
        if (ocfs2_mount_local(osb))
                goto out;
 
@@ -2298,7 +2304,7 @@ int ocfs2_inode_lock_full_nested(struct inode *inode,
        if (ocfs2_is_hard_readonly(osb)) {
                if (ex)
                        status = -EROFS;
-               goto bail;
+               goto getbh;
        }
 
        if (ocfs2_mount_local(osb))
@@ -2356,7 +2362,7 @@ local:
                        mlog_errno(status);
                goto bail;
        }
-
+getbh:
        if (ret_bh) {
                status = ocfs2_assign_bh(inode, ret_bh, local_bh);
                if (status < 0) {
@@ -2628,8 +2634,11 @@ int ocfs2_dentry_lock(struct dentry *dentry, int ex)
 
        BUG_ON(!dl);
 
-       if (ocfs2_is_hard_readonly(osb))
-               return -EROFS;
+       if (ocfs2_is_hard_readonly(osb)) {
+               if (ex)
+                       return -EROFS;
+               return 0;
+       }
 
        if (ocfs2_mount_local(osb))
                return 0;
@@ -2647,7 +2656,7 @@ void ocfs2_dentry_unlock(struct dentry *dentry, int ex)
        struct ocfs2_dentry_lock *dl = dentry->d_fsdata;
        struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);
 
-       if (!ocfs2_mount_local(osb))
+       if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))
                ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);
 }
 
index 23457b4..2f5b92e 100644 (file)
@@ -832,6 +832,102 @@ out:
        return ret;
 }
 
+int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin)
+{
+       struct inode *inode = file->f_mapping->host;
+       int ret;
+       unsigned int is_last = 0, is_data = 0;
+       u16 cs_bits = OCFS2_SB(inode->i_sb)->s_clustersize_bits;
+       u32 cpos, cend, clen, hole_size;
+       u64 extoff, extlen;
+       struct buffer_head *di_bh = NULL;
+       struct ocfs2_extent_rec rec;
+
+       BUG_ON(origin != SEEK_DATA && origin != SEEK_HOLE);
+
+       ret = ocfs2_inode_lock(inode, &di_bh, 0);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+       down_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+       if (*offset >= inode->i_size) {
+               ret = -ENXIO;
+               goto out_unlock;
+       }
+
+       if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
+               if (origin == SEEK_HOLE)
+                       *offset = inode->i_size;
+               goto out_unlock;
+       }
+
+       clen = 0;
+       cpos = *offset >> cs_bits;
+       cend = ocfs2_clusters_for_bytes(inode->i_sb, inode->i_size);
+
+       while (cpos < cend && !is_last) {
+               ret = ocfs2_get_clusters_nocache(inode, di_bh, cpos, &hole_size,
+                                                &rec, &is_last);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out_unlock;
+               }
+
+               extoff = cpos;
+               extoff <<= cs_bits;
+
+               if (rec.e_blkno == 0ULL) {
+                       clen = hole_size;
+                       is_data = 0;
+               } else {
+                       clen = le16_to_cpu(rec.e_leaf_clusters) -
+                               (cpos - le32_to_cpu(rec.e_cpos));
+                       is_data = (rec.e_flags & OCFS2_EXT_UNWRITTEN) ?  0 : 1;
+               }
+
+               if ((!is_data && origin == SEEK_HOLE) ||
+                   (is_data && origin == SEEK_DATA)) {
+                       if (extoff > *offset)
+                               *offset = extoff;
+                       goto out_unlock;
+               }
+
+               if (!is_last)
+                       cpos += clen;
+       }
+
+       if (origin == SEEK_HOLE) {
+               extoff = cpos;
+               extoff <<= cs_bits;
+               extlen = clen;
+               extlen <<=  cs_bits;
+
+               if ((extoff + extlen) > inode->i_size)
+                       extlen = inode->i_size - extoff;
+               extoff += extlen;
+               if (extoff > *offset)
+                       *offset = extoff;
+               goto out_unlock;
+       }
+
+       ret = -ENXIO;
+
+out_unlock:
+
+       brelse(di_bh);
+
+       up_read(&OCFS2_I(inode)->ip_alloc_sem);
+
+       ocfs2_inode_unlock(inode, 0);
+out:
+       if (ret && ret != -ENXIO)
+               ret = -ENXIO;
+       return ret;
+}
+
 int ocfs2_read_virt_blocks(struct inode *inode, u64 v_block, int nr,
                           struct buffer_head *bhs[], int flags,
                           int (*validate)(struct super_block *sb,
index e79d41c..67ea57d 100644 (file)
@@ -53,6 +53,8 @@ int ocfs2_extent_map_get_blocks(struct inode *inode, u64 v_blkno, u64 *p_blkno,
 int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                 u64 map_start, u64 map_len);
 
+int ocfs2_seek_data_hole_offset(struct file *file, loff_t *offset, int origin);
+
 int ocfs2_xattr_get_clusters(struct inode *inode, u32 v_cluster,
                             u32 *p_cluster, u32 *num_clusters,
                             struct ocfs2_extent_list *el,
index de4ea1a..6e39668 100644 (file)
@@ -1950,6 +1950,9 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode,
        if (ret < 0)
                mlog_errno(ret);
 
+       if (file->f_flags & O_SYNC)
+               handle->h_sync = 1;
+
        ocfs2_commit_trans(osb, handle);
 
 out_inode_unlock:
@@ -2052,6 +2055,23 @@ out:
        return ret;
 }
 
+static void ocfs2_aiodio_wait(struct inode *inode)
+{
+       wait_queue_head_t *wq = ocfs2_ioend_wq(inode);
+
+       wait_event(*wq, (atomic_read(&OCFS2_I(inode)->ip_unaligned_aio) == 0));
+}
+
+static int ocfs2_is_io_unaligned(struct inode *inode, size_t count, loff_t pos)
+{
+       int blockmask = inode->i_sb->s_blocksize - 1;
+       loff_t final_size = pos + count;
+
+       if ((pos & blockmask) || (final_size & blockmask))
+               return 1;
+       return 0;
+}
+
 static int ocfs2_prepare_inode_for_refcount(struct inode *inode,
                                            struct file *file,
                                            loff_t pos, size_t count,
@@ -2230,6 +2250,7 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        int full_coherency = !(osb->s_mount_opt &
                               OCFS2_MOUNT_COHERENCY_BUFFERED);
+       int unaligned_dio = 0;
 
        trace_ocfs2_file_aio_write(inode, file, file->f_path.dentry,
                (unsigned long long)OCFS2_I(inode)->ip_blkno,
@@ -2297,6 +2318,10 @@ relock:
                goto out;
        }
 
+       if (direct_io && !is_sync_kiocb(iocb))
+               unaligned_dio = ocfs2_is_io_unaligned(inode, iocb->ki_left,
+                                                     *ppos);
+
        /*
         * We can't complete the direct I/O as requested, fall back to
         * buffered I/O.
@@ -2311,6 +2336,18 @@ relock:
                goto relock;
        }
 
+       if (unaligned_dio) {
+               /*
+                * Wait on previous unaligned aio to complete before
+                * proceeding.
+                */
+               ocfs2_aiodio_wait(inode);
+
+               /* Mark the iocb as needing a decrement in ocfs2_dio_end_io */
+               atomic_inc(&OCFS2_I(inode)->ip_unaligned_aio);
+               ocfs2_iocb_set_unaligned_aio(iocb);
+       }
+
        /*
         * To later detect whether a journal commit for sync writes is
         * necessary, we sample i_size, and cluster count here.
@@ -2382,8 +2419,12 @@ out_dio:
        if ((ret == -EIOCBQUEUED) || (!ocfs2_iocb_is_rw_locked(iocb))) {
                rw_level = -1;
                have_alloc_sem = 0;
+               unaligned_dio = 0;
        }
 
+       if (unaligned_dio)
+               atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio);
+
 out:
        if (rw_level != -1)
                ocfs2_rw_unlock(inode, rw_level);
@@ -2591,6 +2632,57 @@ bail:
        return ret;
 }
 
+/* Refer generic_file_llseek_unlocked() */
+static loff_t ocfs2_file_llseek(struct file *file, loff_t offset, int origin)
+{
+       struct inode *inode = file->f_mapping->host;
+       int ret = 0;
+
+       mutex_lock(&inode->i_mutex);
+
+       switch (origin) {
+       case SEEK_SET:
+               break;
+       case SEEK_END:
+               offset += inode->i_size;
+               break;
+       case SEEK_CUR:
+               if (offset == 0) {
+                       offset = file->f_pos;
+                       goto out;
+               }
+               offset += file->f_pos;
+               break;
+       case SEEK_DATA:
+       case SEEK_HOLE:
+               ret = ocfs2_seek_data_hole_offset(file, &offset, origin);
+               if (ret)
+                       goto out;
+               break;
+       default:
+               ret = -EINVAL;
+               goto out;
+       }
+
+       if (offset < 0 && !(file->f_mode & FMODE_UNSIGNED_OFFSET))
+               ret = -EINVAL;
+       if (!ret && offset > inode->i_sb->s_maxbytes)
+               ret = -EINVAL;
+       if (ret)
+               goto out;
+
+       if (offset != file->f_pos) {
+               file->f_pos = offset;
+               file->f_version = 0;
+       }
+
+out:
+       mutex_unlock(&inode->i_mutex);
+       if (ret)
+               return ret;
+       return offset;
+}
+
 const struct inode_operations ocfs2_file_iops = {
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
@@ -2615,7 +2707,7 @@ const struct inode_operations ocfs2_special_file_iops = {
  * ocfs2_fops_no_plocks and ocfs2_dops_no_plocks!
  */
 const struct file_operations ocfs2_fops = {
-       .llseek         = generic_file_llseek,
+       .llseek         = ocfs2_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
        .mmap           = ocfs2_mmap,
@@ -2663,7 +2755,7 @@ const struct file_operations ocfs2_dops = {
  * the cluster.
  */
 const struct file_operations ocfs2_fops_no_plocks = {
-       .llseek         = generic_file_llseek,
+       .llseek         = ocfs2_file_llseek,
        .read           = do_sync_read,
        .write          = do_sync_write,
        .mmap           = ocfs2_mmap,
index a22d2c0..17454a9 100644 (file)
@@ -951,7 +951,7 @@ static void ocfs2_cleanup_delete_inode(struct inode *inode,
        trace_ocfs2_cleanup_delete_inode(
                (unsigned long long)OCFS2_I(inode)->ip_blkno, sync_data);
        if (sync_data)
-               write_inode_now(inode, 1);
+               filemap_write_and_wait(inode->i_mapping);
        truncate_inode_pages(&inode->i_data, 0);
 }
 
index 1c508b1..88924a3 100644 (file)
@@ -43,6 +43,9 @@ struct ocfs2_inode_info
        /* protects extended attribute changes on this inode */
        struct rw_semaphore             ip_xattr_sem;
 
+       /* Number of outstanding AIO's which are not page aligned */
+       atomic_t                        ip_unaligned_aio;
+
        /* These fields are protected by ip_lock */
        spinlock_t                      ip_lock;
        u32                             ip_open_count;
index bc91072..726ff26 100644 (file)
@@ -122,7 +122,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
        if ((oldflags & OCFS2_IMMUTABLE_FL) || ((flags ^ oldflags) &
                (OCFS2_APPEND_FL | OCFS2_IMMUTABLE_FL))) {
                if (!capable(CAP_LINUX_IMMUTABLE))
-                       goto bail_unlock;
+                       goto bail_commit;
        }
 
        ocfs2_inode->ip_attr = flags;
@@ -132,6 +132,7 @@ static int ocfs2_set_inode_attr(struct inode *inode, unsigned flags,
        if (status < 0)
                mlog_errno(status);
 
+bail_commit:
        ocfs2_commit_trans(osb, handle);
 bail_unlock:
        ocfs2_inode_unlock(inode, 1);
@@ -381,7 +382,7 @@ int ocfs2_info_handle_freeinode(struct inode *inode,
        if (!oifi) {
                status = -ENOMEM;
                mlog_errno(status);
-               goto bail;
+               goto out_err;
        }
 
        if (o2info_from_user(*oifi, req))
@@ -431,7 +432,7 @@ bail:
                o2info_set_request_error(&oifi->ifi_req, req);
 
        kfree(oifi);
-
+out_err:
        return status;
 }
 
@@ -666,7 +667,7 @@ int ocfs2_info_handle_freefrag(struct inode *inode,
        if (!oiff) {
                status = -ENOMEM;
                mlog_errno(status);
-               goto bail;
+               goto out_err;
        }
 
        if (o2info_from_user(*oiff, req))
@@ -716,7 +717,7 @@ bail:
                o2info_set_request_error(&oiff->iff_req, req);
 
        kfree(oiff);
-
+out_err:
        return status;
 }
 
index 295d564..0a42ae9 100644 (file)
@@ -1544,9 +1544,9 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
        /* we need to run complete recovery for offline orphan slots */
        ocfs2_replay_map_set_state(osb, REPLAY_NEEDED);
 
-       mlog(ML_NOTICE, "Recovering node %d from slot %d on device (%u,%u)\n",
-            node_num, slot_num,
-            MAJOR(osb->sb->s_dev), MINOR(osb->sb->s_dev));
+       printk(KERN_NOTICE "ocfs2: Begin replay journal (node %d, slot %d) on "\
+              "device (%u,%u)\n", node_num, slot_num, MAJOR(osb->sb->s_dev),
+              MINOR(osb->sb->s_dev));
 
        OCFS2_I(inode)->ip_clusters = le32_to_cpu(fe->i_clusters);
 
@@ -1601,6 +1601,9 @@ static int ocfs2_replay_journal(struct ocfs2_super *osb,
 
        jbd2_journal_destroy(journal);
 
+       printk(KERN_NOTICE "ocfs2: End replay journal (node %d, slot %d) on "\
+              "device (%u,%u)\n", node_num, slot_num, MAJOR(osb->sb->s_dev),
+              MINOR(osb->sb->s_dev));
 done:
        /* drop the lock on this nodes journal */
        if (got_lock)
@@ -1808,6 +1811,20 @@ static inline unsigned long ocfs2_orphan_scan_timeout(void)
  * every slot, queuing a recovery of the slot on the ocfs2_wq thread. This
  * is done to catch any orphans that are left over in orphan directories.
  *
+ * It scans all slots, even ones that are in use. It does so to handle the
+ * case described below:
+ *
+ *   Node 1 has an inode it was using. The dentry went away due to memory
+ *   pressure.  Node 1 closes the inode, but it's on the free list. The node
+ *   has the open lock.
+ *   Node 2 unlinks the inode. It grabs the dentry lock to notify others,
+ *   but node 1 has no dentry and doesn't get the message. It trylocks the
+ *   open lock, sees that another node has a PR, and does nothing.
+ *   Later node 2 runs its orphan dir. It igets the inode, trylocks the
+ *   open lock, sees the PR still, and does nothing.
+ *   Basically, we have to trigger an orphan iput on node 1. The only way
+ *   for this to happen is if node 1 runs node 2's orphan dir.
+ *
  * ocfs2_queue_orphan_scan gets called every ORPHAN_SCAN_SCHEDULE_TIMEOUT
  * seconds.  It gets an EX lock on os_lockres and checks sequence number
  * stored in LVB. If the sequence number has changed, it means some other
index 68cf2f6..a3385b6 100644 (file)
@@ -441,10 +441,11 @@ static inline int ocfs2_mknod_credits(struct super_block *sb, int is_dir,
 #define OCFS2_SIMPLE_DIR_EXTEND_CREDITS (2)
 
 /* file update (nlink, etc) + directory mtime/ctime + dir entry block + quota
- * update on dir + index leaf + dx root update for free list */
+ * update on dir + index leaf + dx root update for free list +
+ * previous dirblock update in the free list */
 static inline int ocfs2_link_credits(struct super_block *sb)
 {
-       return 2*OCFS2_INODE_UPDATE_CREDITS + 3 +
+       return 2*OCFS2_INODE_UPDATE_CREDITS + 4 +
               ocfs2_quota_trans_credits(sb);
 }
 
index 3e9393c..9cd4108 100644 (file)
@@ -61,7 +61,7 @@ static int ocfs2_fault(struct vm_area_struct *area, struct vm_fault *vmf)
 static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
                                struct page *page)
 {
-       int ret;
+       int ret = VM_FAULT_NOPAGE;
        struct inode *inode = file->f_path.dentry->d_inode;
        struct address_space *mapping = inode->i_mapping;
        loff_t pos = page_offset(page);
@@ -71,32 +71,25 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
        void *fsdata;
        loff_t size = i_size_read(inode);
 
-       /*
-        * Another node might have truncated while we were waiting on
-        * cluster locks.
-        * We don't check size == 0 before the shift. This is borrowed
-        * from do_generic_file_read.
-        */
        last_index = (size - 1) >> PAGE_CACHE_SHIFT;
-       if (unlikely(!size || page->index > last_index)) {
-               ret = -EINVAL;
-               goto out;
-       }
 
        /*
-        * The i_size check above doesn't catch the case where nodes
-        * truncated and then re-extended the file. We'll re-check the
-        * page mapping after taking the page lock inside of
-        * ocfs2_write_begin_nolock().
+        * There are cases that lead to the page no longer bebongs to the
+        * mapping.
+        * 1) pagecache truncates locally due to memory pressure.
+        * 2) pagecache truncates when another is taking EX lock against 
+        * inode lock. see ocfs2_data_convert_worker.
+        * 
+        * The i_size check doesn't catch the case where nodes truncated and
+        * then re-extended the file. We'll re-check the page mapping after
+        * taking the page lock inside of ocfs2_write_begin_nolock().
+        *
+        * Let VM retry with these cases.
         */
-       if (!PageUptodate(page) || page->mapping != inode->i_mapping) {
-               /*
-                * the page has been umapped in ocfs2_data_downconvert_worker.
-                * So return 0 here and let VFS retry.
-                */
-               ret = 0;
+       if ((page->mapping != inode->i_mapping) ||
+           (!PageUptodate(page)) ||
+           (page_offset(page) >= size))
                goto out;
-       }
 
        /*
         * Call ocfs2_write_begin() and ocfs2_write_end() to take
@@ -116,17 +109,21 @@ static int __ocfs2_page_mkwrite(struct file *file, struct buffer_head *di_bh,
        if (ret) {
                if (ret != -ENOSPC)
                        mlog_errno(ret);
+               if (ret == -ENOMEM)
+                       ret = VM_FAULT_OOM;
+               else
+                       ret = VM_FAULT_SIGBUS;
                goto out;
        }
 
-       ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
-                                    fsdata);
-       if (ret < 0) {
-               mlog_errno(ret);
+       if (!locked_page) {
+               ret = VM_FAULT_NOPAGE;
                goto out;
        }
+       ret = ocfs2_write_end_nolock(mapping, pos, len, len, locked_page,
+                                    fsdata);
        BUG_ON(ret != len);
-       ret = 0;
+       ret = VM_FAULT_LOCKED;
 out:
        return ret;
 }
@@ -168,8 +165,6 @@ static int ocfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 out:
        ocfs2_unblock_signals(&oldset);
-       if (ret)
-               ret = VM_FAULT_SIGBUS;
        return ret;
 }
 
index d53cb70..184c76b 100644 (file)
@@ -745,7 +745,7 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
         */
        ocfs2_probe_alloc_group(inode, gd_bh, &goal_bit, len, move_max_hop,
                                new_phys_cpos);
-       if (!new_phys_cpos) {
+       if (!*new_phys_cpos) {
                ret = -ENOSPC;
                goto out_commit;
        }
index 4092858..d355e6e 100644 (file)
@@ -836,18 +836,65 @@ static inline unsigned int ocfs2_clusters_to_megabytes(struct super_block *sb,
 
 static inline void _ocfs2_set_bit(unsigned int bit, unsigned long *bitmap)
 {
-       __test_and_set_bit_le(bit, bitmap);
+       __set_bit_le(bit, bitmap);
 }
 #define ocfs2_set_bit(bit, addr) _ocfs2_set_bit((bit), (unsigned long *)(addr))
 
 static inline void _ocfs2_clear_bit(unsigned int bit, unsigned long *bitmap)
 {
-       __test_and_clear_bit_le(bit, bitmap);
+       __clear_bit_le(bit, bitmap);
 }
 #define ocfs2_clear_bit(bit, addr) _ocfs2_clear_bit((bit), (unsigned long *)(addr))
 
 #define ocfs2_test_bit test_bit_le
 #define ocfs2_find_next_zero_bit find_next_zero_bit_le
 #define ocfs2_find_next_bit find_next_bit_le
+
+static inline void *correct_addr_and_bit_unaligned(int *bit, void *addr)
+{
+#if BITS_PER_LONG == 64
+       *bit += ((unsigned long) addr & 7UL) << 3;
+       addr = (void *) ((unsigned long) addr & ~7UL);
+#elif BITS_PER_LONG == 32
+       *bit += ((unsigned long) addr & 3UL) << 3;
+       addr = (void *) ((unsigned long) addr & ~3UL);
+#else
+#error "how many bits you are?!"
+#endif
+       return addr;
+}
+
+static inline void ocfs2_set_bit_unaligned(int bit, void *bitmap)
+{
+       bitmap = correct_addr_and_bit_unaligned(&bit, bitmap);
+       ocfs2_set_bit(bit, bitmap);
+}
+
+static inline void ocfs2_clear_bit_unaligned(int bit, void *bitmap)
+{
+       bitmap = correct_addr_and_bit_unaligned(&bit, bitmap);
+       ocfs2_clear_bit(bit, bitmap);
+}
+
+static inline int ocfs2_test_bit_unaligned(int bit, void *bitmap)
+{
+       bitmap = correct_addr_and_bit_unaligned(&bit, bitmap);
+       return ocfs2_test_bit(bit, bitmap);
+}
+
+static inline int ocfs2_find_next_zero_bit_unaligned(void *bitmap, int max,
+                                                       int start)
+{
+       int fix = 0, ret, tmpmax;
+       bitmap = correct_addr_and_bit_unaligned(&fix, bitmap);
+       tmpmax = max + fix;
+       start += fix;
+
+       ret = ocfs2_find_next_zero_bit(bitmap, tmpmax, start) - fix;
+       if (ret > max)
+               return max;
+       return ret;
+}
+
 #endif  /* OCFS2_H */
 
index dc8007f..f100bf7 100644 (file)
@@ -404,7 +404,9 @@ struct ocfs2_quota_recovery *ocfs2_begin_quota_recovery(
        int status = 0;
        struct ocfs2_quota_recovery *rec;
 
-       mlog(ML_NOTICE, "Beginning quota recovery in slot %u\n", slot_num);
+       printk(KERN_NOTICE "ocfs2: Beginning quota recovery on device (%s) for "
+              "slot %u\n", osb->dev_str, slot_num);
+
        rec = ocfs2_alloc_quota_recovery();
        if (!rec)
                return ERR_PTR(-ENOMEM);
@@ -549,8 +551,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
                                goto out_commit;
                        }
                        lock_buffer(qbh);
-                       WARN_ON(!ocfs2_test_bit(bit, dchunk->dqc_bitmap));
-                       ocfs2_clear_bit(bit, dchunk->dqc_bitmap);
+                       WARN_ON(!ocfs2_test_bit_unaligned(bit, dchunk->dqc_bitmap));
+                       ocfs2_clear_bit_unaligned(bit, dchunk->dqc_bitmap);
                        le32_add_cpu(&dchunk->dqc_free, 1);
                        unlock_buffer(qbh);
                        ocfs2_journal_dirty(handle, qbh);
@@ -596,7 +598,9 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
        struct inode *lqinode;
        unsigned int flags;
 
-       mlog(ML_NOTICE, "Finishing quota recovery in slot %u\n", slot_num);
+       printk(KERN_NOTICE "ocfs2: Finishing quota recovery on device (%s) for "
+              "slot %u\n", osb->dev_str, slot_num);
+
        mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
        for (type = 0; type < MAXQUOTAS; type++) {
                if (list_empty(&(rec->r_list[type])))
@@ -612,8 +616,9 @@ int ocfs2_finish_quota_recovery(struct ocfs2_super *osb,
                /* Someone else is holding the lock? Then he must be
                 * doing the recovery. Just skip the file... */
                if (status == -EAGAIN) {
-                       mlog(ML_NOTICE, "skipping quota recovery for slot %d "
-                            "because quota file is locked.\n", slot_num);
+                       printk(KERN_NOTICE "ocfs2: Skipping quota recovery on "
+                              "device (%s) for slot %d because quota file is "
+                              "locked.\n", osb->dev_str, slot_num);
                        status = 0;
                        goto out_put;
                } else if (status < 0) {
@@ -944,7 +949,7 @@ static struct ocfs2_quota_chunk *ocfs2_find_free_entry(struct super_block *sb,
                      * ol_quota_entries_per_block(sb);
        }
 
-       found = ocfs2_find_next_zero_bit(dchunk->dqc_bitmap, len, 0);
+       found = ocfs2_find_next_zero_bit_unaligned(dchunk->dqc_bitmap, len, 0);
        /* We failed? */
        if (found == len) {
                mlog(ML_ERROR, "Did not find empty entry in chunk %d with %u"
@@ -1208,7 +1213,7 @@ static void olq_alloc_dquot(struct buffer_head *bh, void *private)
        struct ocfs2_local_disk_chunk *dchunk;
 
        dchunk = (struct ocfs2_local_disk_chunk *)bh->b_data;
-       ocfs2_set_bit(*offset, dchunk->dqc_bitmap);
+       ocfs2_set_bit_unaligned(*offset, dchunk->dqc_bitmap);
        le32_add_cpu(&dchunk->dqc_free, -1);
 }
 
@@ -1289,7 +1294,7 @@ int ocfs2_local_release_dquot(handle_t *handle, struct dquot *dquot)
                        (od->dq_chunk->qc_headerbh->b_data);
        /* Mark structure as freed */
        lock_buffer(od->dq_chunk->qc_headerbh);
-       ocfs2_clear_bit(offset, dchunk->dqc_bitmap);
+       ocfs2_clear_bit_unaligned(offset, dchunk->dqc_bitmap);
        le32_add_cpu(&dchunk->dqc_free, 1);
        unlock_buffer(od->dq_chunk->qc_headerbh);
        ocfs2_journal_dirty(handle, od->dq_chunk->qc_headerbh);
index 26fc001..1424c15 100644 (file)
@@ -493,8 +493,8 @@ int ocfs2_find_slot(struct ocfs2_super *osb)
                        goto bail;
                }
        } else
-               mlog(ML_NOTICE, "slot %d is already allocated to this node!\n",
-                    slot);
+               printk(KERN_INFO "ocfs2: Slot %d on device (%s) was already "
+                      "allocated to this node!\n", slot, osb->dev_str);
 
        ocfs2_set_slot(si, slot, osb->node_num);
        osb->slot_num = slot;
index 19965b0..9436801 100644 (file)
@@ -28,6 +28,7 @@
 #include "cluster/masklog.h"
 #include "cluster/nodemanager.h"
 #include "cluster/heartbeat.h"
+#include "cluster/tcp.h"
 
 #include "stackglue.h"
 
@@ -255,6 +256,61 @@ static void o2cb_dump_lksb(struct ocfs2_dlm_lksb *lksb)
        dlm_print_one_lock(lksb->lksb_o2dlm.lockid);
 }
 
+/*
+ * Check if this node is heartbeating and is connected to all other
+ * heartbeating nodes.
+ */
+static int o2cb_cluster_check(void)
+{
+       u8 node_num;
+       int i;
+       unsigned long hbmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+       unsigned long netmap[BITS_TO_LONGS(O2NM_MAX_NODES)];
+
+       node_num = o2nm_this_node();
+       if (node_num == O2NM_MAX_NODES) {
+               printk(KERN_ERR "o2cb: This node has not been configured.\n");
+               return -EINVAL;
+       }
+
+       /*
+        * o2dlm expects o2net sockets to be created. If not, then
+        * dlm_join_domain() fails with a stack of errors which are both cryptic
+        * and incomplete. The idea here is to detect upfront whether we have
+        * managed to connect to all nodes or not. If not, then list the nodes
+        * to allow the user to check the configuration (incorrect IP, firewall,
+        * etc.) Yes, this is racy. But its not the end of the world.
+        */
+#define        O2CB_MAP_STABILIZE_COUNT        60
+       for (i = 0; i < O2CB_MAP_STABILIZE_COUNT; ++i) {
+               o2hb_fill_node_map(hbmap, sizeof(hbmap));
+               if (!test_bit(node_num, hbmap)) {
+                       printk(KERN_ERR "o2cb: %s heartbeat has not been "
+                              "started.\n", (o2hb_global_heartbeat_active() ?
+                                             "Global" : "Local"));
+                       return -EINVAL;
+               }
+               o2net_fill_node_map(netmap, sizeof(netmap));
+               /* Force set the current node to allow easy compare */
+               set_bit(node_num, netmap);
+               if (!memcmp(hbmap, netmap, sizeof(hbmap)))
+                       return 0;
+               if (i < O2CB_MAP_STABILIZE_COUNT)
+                       msleep(1000);
+       }
+
+       printk(KERN_ERR "o2cb: This node could not connect to nodes:");
+       i = -1;
+       while ((i = find_next_bit(hbmap, O2NM_MAX_NODES,
+                                 i + 1)) < O2NM_MAX_NODES) {
+               if (!test_bit(i, netmap))
+                       printk(" %u", i);
+       }
+       printk(".\n");
+
+       return -ENOTCONN;
+}
+
 /*
  * Called from the dlm when it's about to evict a node. This is how the
  * classic stack signals node death.
@@ -263,8 +319,8 @@ static void o2dlm_eviction_cb(int node_num, void *data)
 {
        struct ocfs2_cluster_connection *conn = data;
 
-       mlog(ML_NOTICE, "o2dlm has evicted node %d from group %.*s\n",
-            node_num, conn->cc_namelen, conn->cc_name);
+       printk(KERN_NOTICE "o2cb: o2dlm has evicted node %d from domain %.*s\n",
+              node_num, conn->cc_namelen, conn->cc_name);
 
        conn->cc_recovery_handler(node_num, conn->cc_recovery_data);
 }
@@ -280,12 +336,11 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn)
        BUG_ON(conn == NULL);
        BUG_ON(conn->cc_proto == NULL);
 
-       /* for now we only have one cluster/node, make sure we see it
-        * in the heartbeat universe */
-       if (!o2hb_check_local_node_heartbeating()) {
-               if (o2hb_global_heartbeat_active())
-                       mlog(ML_ERROR, "Global heartbeat not started\n");
-               rc = -EINVAL;
+       /* Ensure cluster stack is up and all nodes are connected */
+       rc = o2cb_cluster_check();
+       if (rc) {
+               printk(KERN_ERR "o2cb: Cluster check failed. Fix errors "
+                      "before retrying.\n");
                goto out;
        }
 
index 56f6102..4994f8b 100644 (file)
@@ -54,6 +54,7 @@
 #include "ocfs1_fs_compat.h"
 
 #include "alloc.h"
+#include "aops.h"
 #include "blockcheck.h"
 #include "dlmglue.h"
 #include "export.h"
@@ -1107,9 +1108,9 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
 
                ocfs2_set_ro_flag(osb, 1);
 
-               printk(KERN_NOTICE "Readonly device detected. No cluster "
-                      "services will be utilized for this mount. Recovery "
-                      "will be skipped.\n");
+               printk(KERN_NOTICE "ocfs2: Readonly device (%s) detected. "
+                      "Cluster services will not be used for this mount. "
+                      "Recovery will be skipped.\n", osb->dev_str);
        }
 
        if (!ocfs2_is_hard_readonly(osb)) {
@@ -1616,12 +1617,17 @@ static int ocfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
        return 0;
 }
 
+wait_queue_head_t ocfs2__ioend_wq[OCFS2_IOEND_WQ_HASH_SZ];
+
 static int __init ocfs2_init(void)
 {
-       int status;
+       int status, i;
 
        ocfs2_print_version();
 
+       for (i = 0; i < OCFS2_IOEND_WQ_HASH_SZ; i++)
+               init_waitqueue_head(&ocfs2__ioend_wq[i]);
+
        status = init_ocfs2_uptodate_cache();
        if (status < 0) {
                mlog_errno(status);
@@ -1760,7 +1766,7 @@ static void ocfs2_inode_init_once(void *data)
        ocfs2_extent_map_init(&oi->vfs_inode);
        INIT_LIST_HEAD(&oi->ip_io_markers);
        oi->ip_dir_start_lookup = 0;
-
+       atomic_set(&oi->ip_unaligned_aio, 0);
        init_rwsem(&oi->ip_alloc_sem);
        init_rwsem(&oi->ip_xattr_sem);
        mutex_init(&oi->ip_io_mutex);
@@ -1974,7 +1980,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
         * If we failed before we got a uuid_str yet, we can't stop
         * heartbeat.  Otherwise, do it.
         */
-       if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str)
+       if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str &&
+           !ocfs2_is_hard_readonly(osb))
                hangup_needed = 1;
 
        if (osb->cconn)
@@ -2353,7 +2360,7 @@ static int ocfs2_initialize_super(struct super_block *sb,
                mlog_errno(status);
                goto bail;
        }
-       cleancache_init_shared_fs((char *)&uuid_net_key, sb);
+       cleancache_init_shared_fs((char *)&di->id2.i_super.s_uuid, sb);
 
 bail:
        return status;
@@ -2462,8 +2469,8 @@ static int ocfs2_check_volume(struct ocfs2_super *osb)
                        goto finally;
                }
        } else {
-               mlog(ML_NOTICE, "File system was not unmounted cleanly, "
-                    "recovering volume.\n");
+               printk(KERN_NOTICE "ocfs2: File system on device (%s) was not "
+                      "unmounted cleanly, recovering it.\n", osb->dev_str);
        }
 
        local = ocfs2_mount_local(osb);
index 194fb22..aa9e877 100644 (file)
@@ -2376,16 +2376,18 @@ static int ocfs2_remove_value_outside(struct inode*inode,
                }
 
                ret = ocfs2_xattr_value_truncate(inode, vb, 0, &ctxt);
-               if (ret < 0) {
-                       mlog_errno(ret);
-                       break;
-               }
 
                ocfs2_commit_trans(osb, ctxt.handle);
                if (ctxt.meta_ac) {
                        ocfs2_free_alloc_context(ctxt.meta_ac);
                        ctxt.meta_ac = NULL;
                }
+
+               if (ret < 0) {
+                       mlog_errno(ret);
+                       break;
+               }
+
        }
 
        if (ctxt.meta_ac)
index 2db1bd3..851ba3d 100644 (file)
@@ -1652,46 +1652,12 @@ out:
        return error;
 }
 
-static int proc_pid_fd_link_getattr(struct vfsmount *mnt, struct dentry *dentry,
-               struct kstat *stat)
-{
-       struct inode *inode = dentry->d_inode;
-       struct task_struct *task = get_proc_task(inode);
-       int rc;
-
-       if (task == NULL)
-               return -ESRCH;
-
-       rc = -EACCES;
-       if (lock_trace(task))
-               goto out_task;
-
-       generic_fillattr(inode, stat);
-       unlock_trace(task);
-       rc = 0;
-out_task:
-       put_task_struct(task);
-       return rc;
-}
-
 static const struct inode_operations proc_pid_link_inode_operations = {
        .readlink       = proc_pid_readlink,
        .follow_link    = proc_pid_follow_link,
        .setattr        = proc_setattr,
 };
 
-static const struct inode_operations proc_fdinfo_link_inode_operations = {
-       .setattr        = proc_setattr,
-       .getattr        = proc_pid_fd_link_getattr,
-};
-
-static const struct inode_operations proc_fd_link_inode_operations = {
-       .readlink       = proc_pid_readlink,
-       .follow_link    = proc_pid_follow_link,
-       .setattr        = proc_setattr,
-       .getattr        = proc_pid_fd_link_getattr,
-};
-
 
 /* building an inode */
 
@@ -1923,61 +1889,49 @@ out:
 
 static int proc_fd_info(struct inode *inode, struct path *path, char *info)
 {
-       struct task_struct *task;
-       struct files_struct *files;
+       struct task_struct *task = get_proc_task(inode);
+       struct files_struct *files = NULL;
        struct file *file;
        int fd = proc_fd(inode);
-       int rc;
-
-       task = get_proc_task(inode);
-       if (!task)
-               return -ENOENT;
-
-       rc = -EACCES;
-       if (lock_trace(task))
-               goto out_task;
-
-       rc = -ENOENT;
-       files = get_files_struct(task);
-       if (files == NULL)
-               goto out_unlock;
 
-       /*
-        * We are not taking a ref to the file structure, so we must
-        * hold ->file_lock.
-        */
-       spin_lock(&files->file_lock);
-       file = fcheck_files(files, fd);
-       if (file) {
-               unsigned int f_flags;
-               struct fdtable *fdt;
-
-               fdt = files_fdtable(files);
-               f_flags = file->f_flags & ~O_CLOEXEC;
-               if (FD_ISSET(fd, fdt->close_on_exec))
-                       f_flags |= O_CLOEXEC;
-
-               if (path) {
-                       *path = file->f_path;
-                       path_get(&file->f_path);
+       if (task) {
+               files = get_files_struct(task);
+               put_task_struct(task);
+       }
+       if (files) {
+               /*
+                * We are not taking a ref to the file structure, so we must
+                * hold ->file_lock.
+                */
+               spin_lock(&files->file_lock);
+               file = fcheck_files(files, fd);
+               if (file) {
+                       unsigned int f_flags;
+                       struct fdtable *fdt;
+
+                       fdt = files_fdtable(files);
+                       f_flags = file->f_flags & ~O_CLOEXEC;
+                       if (FD_ISSET(fd, fdt->close_on_exec))
+                               f_flags |= O_CLOEXEC;
+
+                       if (path) {
+                               *path = file->f_path;
+                               path_get(&file->f_path);
+                       }
+                       if (info)
+                               snprintf(info, PROC_FDINFO_MAX,
+                                        "pos:\t%lli\n"
+                                        "flags:\t0%o\n",
+                                        (long long) file->f_pos,
+                                        f_flags);
+                       spin_unlock(&files->file_lock);
+                       put_files_struct(files);
+                       return 0;
                }
-               if (info)
-                       snprintf(info, PROC_FDINFO_MAX,
-                                "pos:\t%lli\n"
-                                "flags:\t0%o\n",
-                                (long long) file->f_pos,
-                                f_flags);
-               rc = 0;
-       } else
-               rc = -ENOENT;
-       spin_unlock(&files->file_lock);
-       put_files_struct(files);
-
-out_unlock:
-       unlock_trace(task);
-out_task:
-       put_task_struct(task);
-       return rc;
+               spin_unlock(&files->file_lock);
+               put_files_struct(files);
+       }
+       return -ENOENT;
 }
 
 static int proc_fd_link(struct inode *inode, struct path *path)
@@ -2072,7 +2026,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
        spin_unlock(&files->file_lock);
        put_files_struct(files);
 
-       inode->i_op = &proc_fd_link_inode_operations;
+       inode->i_op = &proc_pid_link_inode_operations;
        inode->i_size = 64;
        ei->op.proc_get_link = proc_fd_link;
        d_set_d_op(dentry, &tid_fd_dentry_operations);
@@ -2104,12 +2058,7 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
        if (fd == ~0U)
                goto out;
 
-       result = ERR_PTR(-EACCES);
-       if (lock_trace(task))
-               goto out;
-
        result = instantiate(dir, dentry, task, &fd);
-       unlock_trace(task);
 out:
        put_task_struct(task);
 out_no_task:
@@ -2129,28 +2078,23 @@ static int proc_readfd_common(struct file * filp, void * dirent,
        retval = -ENOENT;
        if (!p)
                goto out_no_task;
-
-       retval = -EACCES;
-       if (lock_trace(p))
-               goto out;
-
        retval = 0;
 
        fd = filp->f_pos;
        switch (fd) {
                case 0:
                        if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
-                               goto out_unlock;
+                               goto out;
                        filp->f_pos++;
                case 1:
                        ino = parent_ino(dentry);
                        if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
-                               goto out_unlock;
+                               goto out;
                        filp->f_pos++;
                default:
                        files = get_files_struct(p);
                        if (!files)
-                               goto out_unlock;
+                               goto out;
                        rcu_read_lock();
                        for (fd = filp->f_pos-2;
                             fd < files_fdtable(files)->max_fds;
@@ -2174,9 +2118,6 @@ static int proc_readfd_common(struct file * filp, void * dirent,
                        rcu_read_unlock();
                        put_files_struct(files);
        }
-
-out_unlock:
-       unlock_trace(p);
 out:
        put_task_struct(p);
 out_no_task:
@@ -2254,7 +2195,6 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
        ei->fd = fd;
        inode->i_mode = S_IFREG | S_IRUSR;
        inode->i_fop = &proc_fdinfo_file_operations;
-       inode->i_op = &proc_fdinfo_link_inode_operations;
        d_set_d_op(dentry, &tid_fd_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
index 2bd620f..57bbf90 100644 (file)
@@ -167,6 +167,7 @@ int pstore_register(struct pstore_info *psi)
        }
 
        psinfo = psi;
+       mutex_init(&psinfo->read_mutex);
        spin_unlock(&pstore_lock);
 
        if (owner && !try_module_get(owner)) {
@@ -195,30 +196,32 @@ EXPORT_SYMBOL_GPL(pstore_register);
 void pstore_get_records(int quiet)
 {
        struct pstore_info *psi = psinfo;
+       char                    *buf = NULL;
        ssize_t                 size;
        u64                     id;
        enum pstore_type_id     type;
        struct timespec         time;
        int                     failed = 0, rc;
-       unsigned long           flags;
 
        if (!psi)
                return;
 
-       spin_lock_irqsave(&psinfo->buf_lock, flags);
+       mutex_lock(&psi->read_mutex);
        rc = psi->open(psi);
        if (rc)
                goto out;
 
-       while ((size = psi->read(&id, &type, &time, psi)) > 0) {
-               rc = pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
+       while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) {
+               rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size,
                                  time, psi);
+               kfree(buf);
+               buf = NULL;
                if (rc && (rc != -EEXIST || !quiet))
                        failed++;
        }
        psi->close(psi);
 out:
-       spin_unlock_irqrestore(&psinfo->buf_lock, flags);
+       mutex_unlock(&psi->read_mutex);
 
        if (failed)
                printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
index 33b1331..574d4ee 100644 (file)
@@ -189,7 +189,7 @@ xfs_end_io(
        int             error = 0;
 
        if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
-               error = -EIO;
+               ioend->io_error = -EIO;
                goto done;
        }
        if (ioend->io_error)
index 1a35138..eac97ef 100644 (file)
@@ -656,7 +656,7 @@ xfs_buf_item_committing(
 /*
  * This is the ops vector shared by all buf log items.
  */
-static struct xfs_item_ops xfs_buf_item_ops = {
+static const struct xfs_item_ops xfs_buf_item_ops = {
        .iop_size       = xfs_buf_item_size,
        .iop_format     = xfs_buf_item_format,
        .iop_pin        = xfs_buf_item_pin,
index bb3f71d..0dee0b7 100644 (file)
@@ -295,7 +295,7 @@ xfs_qm_dquot_logitem_committing(
 /*
  * This is the ops vector for dquots
  */
-static struct xfs_item_ops xfs_dquot_item_ops = {
+static const struct xfs_item_ops xfs_dquot_item_ops = {
        .iop_size       = xfs_qm_dquot_logitem_size,
        .iop_format     = xfs_qm_dquot_logitem_format,
        .iop_pin        = xfs_qm_dquot_logitem_pin,
@@ -483,7 +483,7 @@ xfs_qm_qoff_logitem_committing(
 {
 }
 
-static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
+static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
        .iop_size       = xfs_qm_qoff_logitem_size,
        .iop_format     = xfs_qm_qoff_logitem_format,
        .iop_pin        = xfs_qm_qoff_logitem_pin,
@@ -498,7 +498,7 @@ static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = {
 /*
  * This is the ops vector shared by all quotaoff-start log items.
  */
-static struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
+static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = {
        .iop_size       = xfs_qm_qoff_logitem_size,
        .iop_format     = xfs_qm_qoff_logitem_format,
        .iop_pin        = xfs_qm_qoff_logitem_pin,
index d22e626..35c2aff 100644 (file)
@@ -217,7 +217,7 @@ xfs_efi_item_committing(
 /*
  * This is the ops vector shared by all efi log items.
  */
-static struct xfs_item_ops xfs_efi_item_ops = {
+static const struct xfs_item_ops xfs_efi_item_ops = {
        .iop_size       = xfs_efi_item_size,
        .iop_format     = xfs_efi_item_format,
        .iop_pin        = xfs_efi_item_pin,
@@ -477,7 +477,7 @@ xfs_efd_item_committing(
 /*
  * This is the ops vector shared by all efd log items.
  */
-static struct xfs_item_ops xfs_efd_item_ops = {
+static const struct xfs_item_ops xfs_efd_item_ops = {
        .iop_size       = xfs_efd_item_size,
        .iop_format     = xfs_efd_item_format,
        .iop_pin        = xfs_efd_item_pin,
index b7cf21b..abaafdb 100644 (file)
@@ -795,7 +795,7 @@ xfs_inode_item_committing(
 /*
  * This is the ops vector shared by all buf log items.
  */
-static struct xfs_item_ops xfs_inode_item_ops = {
+static const struct xfs_item_ops xfs_inode_item_ops = {
        .iop_size       = xfs_inode_item_size,
        .iop_format     = xfs_inode_item_format,
        .iop_pin        = xfs_inode_item_pin,
index 2758a62..a14cd89 100644 (file)
@@ -626,7 +626,7 @@ xfs_log_item_init(
        struct xfs_mount        *mp,
        struct xfs_log_item     *item,
        int                     type,
-       struct xfs_item_ops     *ops)
+       const struct xfs_item_ops *ops)
 {
        item->li_mountp = mp;
        item->li_ailp = mp->m_ail;
index 78c9039..3f7bf45 100644 (file)
@@ -137,7 +137,7 @@ struct xfs_trans;
 void   xfs_log_item_init(struct xfs_mount      *mp,
                        struct xfs_log_item     *item,
                        int                     type,
-                       struct xfs_item_ops     *ops);
+                       const struct xfs_item_ops *ops);
 
 xfs_lsn_t xfs_log_done(struct xfs_mount *mp,
                       struct xlog_ticket *ticket,
index 5cff443..0bbb1a4 100644 (file)
@@ -674,7 +674,8 @@ xfs_qm_dqattach_one(
         * disk and we didn't ask it to allocate;
         * ESRCH if quotas got turned off suddenly.
         */
-       error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp);
+       error = xfs_qm_dqget(ip->i_mount, ip, id, type,
+                            doalloc | XFS_QMOPT_DOWARN, &dqp);
        if (error)
                return error;
 
index 603f3eb..3ae713c 100644 (file)
@@ -326,7 +326,7 @@ typedef struct xfs_log_item {
                                                 struct xfs_log_item *);
                                                        /* buffer item iodone */
                                                        /* callback func */
-       struct xfs_item_ops             *li_ops;        /* function list */
+       const struct xfs_item_ops       *li_ops;        /* function list */
 
        /* delayed logging */
        struct list_head                li_cil;         /* CIL pointers */
@@ -341,7 +341,7 @@ typedef struct xfs_log_item {
        { XFS_LI_IN_AIL,        "IN_AIL" }, \
        { XFS_LI_ABORTED,       "ABORTED" }
 
-typedef struct xfs_item_ops {
+struct xfs_item_ops {
        uint (*iop_size)(xfs_log_item_t *);
        void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *);
        void (*iop_pin)(xfs_log_item_t *);
@@ -352,7 +352,7 @@ typedef struct xfs_item_ops {
        void (*iop_push)(xfs_log_item_t *);
        bool (*iop_pushbuf)(xfs_log_item_t *);
        void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t);
-} xfs_item_ops_t;
+};
 
 #define IOP_SIZE(ip)           (*(ip)->li_ops->iop_size)(ip)
 #define IOP_FORMAT(ip,vp)      (*(ip)->li_ops->iop_format)(ip, vp)
index 4ecf2a5..ce9268a 100644 (file)
@@ -112,7 +112,7 @@ xfs_readlink(
        char            *link)
 {
        xfs_mount_t     *mp = ip->i_mount;
-       int             pathlen;
+       xfs_fsize_t     pathlen;
        int             error = 0;
 
        trace_xfs_readlink(ip);
@@ -122,13 +122,19 @@ xfs_readlink(
 
        xfs_ilock(ip, XFS_ILOCK_SHARED);
 
-       ASSERT(S_ISLNK(ip->i_d.di_mode));
-       ASSERT(ip->i_d.di_size <= MAXPATHLEN);
-
        pathlen = ip->i_d.di_size;
        if (!pathlen)
                goto out;
 
+       if (pathlen < 0 || pathlen > MAXPATHLEN) {
+               xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)",
+                        __func__, (unsigned long long) ip->i_ino,
+                        (long long) pathlen);
+               ASSERT(0);
+               return XFS_ERROR(EFSCORRUPTED);
+       }
+
+
        if (ip->i_df.if_flags & XFS_IFINLINE) {
                memcpy(link, ip->i_df.if_u1.if_data, pathlen);
                link[pathlen] = '\0';
index cf39949..1f9e951 100644 (file)
@@ -990,7 +990,9 @@ struct drm_minor {
        struct proc_dir_entry *proc_root;  /**< proc directory entry */
        struct drm_info_node proc_nodes;
        struct dentry *debugfs_root;
-       struct drm_info_node debugfs_nodes;
+
+       struct list_head debugfs_list;
+       struct mutex debugfs_lock; /* Protects debugfs_list. */
 
        struct drm_master *master; /* currently active master for this node */
        struct list_head master_list;
index d30bedf..ddd46db 100644 (file)
@@ -235,6 +235,8 @@ struct drm_mode_fb_cmd {
 #define DRM_MODE_FB_DIRTY_ANNOTATE_FILL 0x02
 #define DRM_MODE_FB_DIRTY_FLAGS         0x03
 
+#define DRM_MODE_FB_DIRTY_MAX_CLIPS     256
+
 /*
  * Mark a region of a framebuffer as dirty.
  *
index 3d53efd..f81676f 100644 (file)
@@ -4,6 +4,7 @@
 */
 #define radeon_PCI_IDS \
        {0x1002, 0x3150, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x3151, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x3152, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x3154, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x3155, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV380|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
@@ -55,6 +56,7 @@
        {0x1002, 0x4C64, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4C66, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4C67, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV250|RADEON_IS_MOBILITY}, \
+       {0x1002, 0x4C6E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|RADEON_IS_MOBILITY}, \
        {0x1002, 0x4E44, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
        {0x1002, 0x4E46, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_R300}, \
index 874c4d2..1205043 100644 (file)
 /**
  * User-desired buffer creation information structure.
  *
- * @size: requested size for the object.
+ * @size: user-desired memory allocation size.
  *     - this size value would be page-aligned internally.
  * @flags: user request for setting memory type or cache attributes.
- * @handle: returned handle for the object.
+ * @handle: returned a handle to created gem object.
+ *     - this handle will be set by gem module of kernel side.
  */
 struct drm_exynos_gem_create {
-       unsigned int size;
+       uint64_t size;
        unsigned int flags;
        unsigned int handle;
 };
index b65be60..be94be6 100644 (file)
@@ -874,6 +874,10 @@ struct drm_radeon_gem_pwrite {
 
 #define RADEON_CHUNK_ID_RELOCS 0x01
 #define RADEON_CHUNK_ID_IB     0x02
+#define RADEON_CHUNK_ID_FLAGS  0x03
+
+/* The first dword of RADEON_CHUNK_ID_FLAGS is a uint32 of these flags: */
+#define RADEON_CS_KEEP_TILING_FLAGS 0x01
 
 struct drm_radeon_cs_chunk {
        uint32_t                chunk_id;
index a3c071c..847994a 100644 (file)
@@ -211,8 +211,8 @@ extern void bio_pair_release(struct bio_pair *dbio);
 extern struct bio_set *bioset_create(unsigned int, unsigned int);
 extern void bioset_free(struct bio_set *);
 
-extern struct bio *bio_alloc(gfp_t, int);
-extern struct bio *bio_kmalloc(gfp_t, int);
+extern struct bio *bio_alloc(gfp_t, unsigned int);
+extern struct bio *bio_kmalloc(gfp_t, unsigned int);
 extern struct bio *bio_alloc_bioset(gfp_t, int, struct bio_set *);
 extern void bio_put(struct bio *);
 extern void bio_free(struct bio *, struct bio_set *);
@@ -519,7 +519,11 @@ extern void bio_integrity_init(void);
 #define bioset_integrity_create(a, b)  (0)
 #define bio_integrity_prep(a)          (0)
 #define bio_integrity_enabled(a)       (0)
-#define bio_integrity_clone(a, b, c, d)        (0)
+static inline int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
+                                     gfp_t gfp_mask, struct bio_set *bs)
+{
+       return 0;
+}
 #define bioset_integrity_free(a)       do { } while (0)
 #define bio_integrity_free(a, b)       do { } while (0)
 #define bio_integrity_endio(a, b)      do { } while (0)
index f88eacb..7c05ac2 100644 (file)
 #include "osdmap.h"
 #include "messenger.h"
 
+/* 
+ * Maximum object name size 
+ * (must be at least as big as RBD_MAX_MD_NAME_LEN -- currently 100) 
+ */
+#define MAX_OBJ_NAME_SIZE 100
+
 struct ceph_msg;
 struct ceph_snap_context;
 struct ceph_osd_request;
@@ -75,7 +81,7 @@ struct ceph_osd_request {
        struct inode *r_inode;                /* for use by callbacks */
        void *r_priv;                         /* ditto */
 
-       char              r_oid[40];          /* object name */
+       char              r_oid[MAX_OBJ_NAME_SIZE];          /* object name */
        int               r_oid_len;
        unsigned long     r_stamp;            /* send OR check time */
 
index 139c4db..c86c940 100644 (file)
@@ -156,6 +156,7 @@ extern u64 timecounter_cyc2time(struct timecounter *tc,
  * @mult:              cycle to nanosecond multiplier
  * @shift:             cycle to nanosecond divisor (power of two)
  * @max_idle_ns:       max idle time permitted by the clocksource (nsecs)
+ * @maxadj             maximum adjustment value to mult (~11%)
  * @flags:             flags describing special properties
  * @archdata:          arch-specific data
  * @suspend:           suspend function for the clocksource, if necessary
@@ -172,7 +173,7 @@ struct clocksource {
        u32 mult;
        u32 shift;
        u64 max_idle_ns;
-
+       u32 maxadj;
 #ifdef CONFIG_ARCH_CLOCKSOURCE_DATA
        struct arch_clocksource_data archdata;
 #endif
index afb9458..98ce812 100644 (file)
@@ -41,7 +41,7 @@ struct devfreq_dev_status {
        unsigned long total_time;
        unsigned long busy_time;
        unsigned long current_frequency;
-       void *private_date;
+       void *private_data;
 };
 
 /**
index ffbcf95..3136ede 100644 (file)
@@ -69,7 +69,7 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
  * @resume:    Called to bring a device on this bus out of sleep mode.
  * @pm:                Power management operations of this bus, callback the specific
  *             device driver's pm-ops.
- * @iommu_ops   IOMMU specific operations for this bus, used to attach IOMMU
+ * @iommu_ops:  IOMMU specific operations for this bus, used to attach IOMMU
  *              driver implementations to a bus and allow the driver to do
  *              bus-specific setup
  * @p:         The private data of the driver core, only the driver core can
@@ -682,6 +682,11 @@ static inline bool device_async_suspend_enabled(struct device *dev)
        return !!dev->power.async_suspend;
 }
 
+static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
+{
+       dev->power.ignore_children = enable;
+}
+
 static inline void device_lock(struct device *dev)
 {
        mutex_lock(&dev->mutex);
index 0c4df26..e313022 100644 (file)
@@ -1886,6 +1886,7 @@ extern struct dentry *mount_single(struct file_system_type *fs_type,
 extern struct dentry *mount_nodev(struct file_system_type *fs_type,
        int flags, void *data,
        int (*fill_super)(struct super_block *, void *, int));
+extern struct dentry *mount_subtree(struct vfsmount *mnt, const char *path);
 void generic_shutdown_super(struct super_block *sb);
 void kill_block_super(struct super_block *sb);
 void kill_anon_super(struct super_block *sb);
index 9de31bc..6d18f35 100644 (file)
@@ -21,8 +21,6 @@
 #define dev_to_part(device)    container_of((device), struct hd_struct, __dev)
 #define disk_to_dev(disk)      (&(disk)->part0.__dev)
 #define part_to_dev(part)      (&((part)->__dev))
-#define alias_name(disk)       ((disk)->alias ? (disk)->alias : \
-                                                (disk)->disk_name)
 
 extern struct device_type part_type;
 extern struct kobject *block_depr;
@@ -60,7 +58,6 @@ enum {
 
 #define DISK_MAX_PARTS                 256
 #define DISK_NAME_LEN                  32
-#define ALIAS_LEN                      256
 
 #include <linux/major.h>
 #include <linux/device.h>
@@ -166,7 +163,6 @@ struct gendisk {
                                          * disks that can't be partitioned. */
 
        char disk_name[DISK_NAME_LEN];  /* name of major driver */
-       char *alias;                    /* alias name of disk */
        char *(*devnode)(struct gendisk *gd, mode_t *mode);
 
        unsigned int events;            /* supported events */
index 19644e0..d9d6c86 100644 (file)
@@ -110,11 +110,6 @@ static inline void copy_huge_page(struct page *dst, struct page *src)
 
 #define hugetlb_change_protection(vma, address, end, newprot)
 
-#ifndef HPAGE_MASK
-#define HPAGE_MASK     PAGE_MASK               /* Keep the compiler happy */
-#define HPAGE_SIZE     PAGE_SIZE
-#endif
-
 #endif /* !CONFIG_HUGETLB_PAGE */
 
 #define HUGETLB_ANON_FILE "anon_hugepage"
index 08a2fee..aad6bd4 100644 (file)
@@ -118,7 +118,6 @@ int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
 static inline
 void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
 {
-       return 0;
 }
 
 static inline int hwspin_lock_get_id(struct hwspinlock *hwlock)
index a81bf6d..07d103a 100644 (file)
@@ -432,9 +432,6 @@ void i2c_unlock_adapter(struct i2c_adapter *);
 /* Internal numbers to terminate lists */
 #define I2C_CLIENT_END         0xfffeU
 
-/* The numbers to use to set I2C bus address */
-#define ANY_I2C_BUS            0xffff
-
 /* Construct an I2C_CLIENT_END-terminated array of i2c addresses */
 #define I2C_ADDRS(addr, addrs...) \
        ((const unsigned short []){ addr, ## addrs, I2C_CLIENT_END })
index 80b480c..abf5028 100644 (file)
@@ -98,9 +98,10 @@ enum {
        INET_DIAG_VEGASINFO,
        INET_DIAG_CONG,
        INET_DIAG_TOS,
+       INET_DIAG_TCLASS,
 };
 
-#define INET_DIAG_MAX INET_DIAG_TOS
+#define INET_DIAG_MAX INET_DIAG_TCLASS
 
 
 /* INET_DIAG_MEM */
index 08ffab0..94b1e35 100644 (file)
@@ -184,7 +184,6 @@ extern struct cred init_cred;
                [PIDTYPE_SID]  = INIT_PID_LINK(PIDTYPE_SID),            \
        },                                                              \
        .thread_group   = LIST_HEAD_INIT(tsk.thread_group),             \
-       .dirties = INIT_PROP_LOCAL_SINGLE(dirties),                     \
        INIT_IDS                                                        \
        INIT_PERF_EVENTS(tsk)                                           \
        INIT_TRACE_IRQFLAGS                                             \
index f47fcd3..c3892fc 100644 (file)
@@ -555,7 +555,6 @@ struct kvm_ppc_pvinfo {
 #define KVM_CAP_PPC_SMT 64
 #define KVM_CAP_PPC_RMA        65
 #define KVM_CAP_MAX_VCPUS 66       /* returns max vcpus per vm */
-#define KVM_CAP_PPC_HIOR 67
 #define KVM_CAP_PPC_PAPR 68
 #define KVM_CAP_S390_GMAP 71
 
index 82b4c88..8bf2cb9 100644 (file)
 
 
 /*Registers VDD1, VDD2 voltage values definitions */
-#define VDD1_2_NUM_VOLTS                               73
+#define VDD1_2_NUM_VOLT_FINE                           73
+#define VDD1_2_NUM_VOLT_COARSE                         3
 #define VDD1_2_MIN_VOLT                                        6000
 #define VDD1_2_OFFSET                                  125
 
index cbeb586..a82ad4d 100644 (file)
@@ -2536,6 +2536,8 @@ extern void               net_disable_timestamp(void);
 extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);
 extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);
 extern void dev_seq_stop(struct seq_file *seq, void *v);
+extern int dev_seq_open_ops(struct inode *inode, struct file *file,
+                           const struct seq_operations *ops);
 #endif
 
 extern int netdev_class_create_file(struct class_attribute *class_attr);
index ab2c634..92ecf55 100644 (file)
@@ -410,6 +410,9 @@ extern const struct inode_operations nfs_file_inode_operations;
 extern const struct inode_operations nfs3_file_inode_operations;
 #endif /* CONFIG_NFS_V3 */
 extern const struct file_operations nfs_file_operations;
+#ifdef CONFIG_NFS_V4
+extern const struct file_operations nfs4_file_operations;
+#endif /* CONFIG_NFS_V4 */
 extern const struct address_space_operations nfs_file_aops;
 extern const struct address_space_operations nfs_dir_aops;
 
index c74595b..2a7c533 100644 (file)
@@ -1192,6 +1192,7 @@ struct nfs_rpc_ops {
        const struct dentry_operations *dentry_ops;
        const struct inode_operations *dir_inode_ops;
        const struct inode_operations *file_inode_ops;
+       const struct file_operations *file_ops;
 
        int     (*getroot) (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fsinfo *);
index e3d0b38..7ef6872 100644 (file)
@@ -12,7 +12,7 @@ struct pci_ats {
        unsigned int is_enabled:1;      /* Enable bit is set */
 };
 
-#ifdef CONFIG_PCI_IOV
+#ifdef CONFIG_PCI_ATS
 
 extern int pci_enable_ats(struct pci_dev *dev, int ps);
 extern void pci_disable_ats(struct pci_dev *dev);
@@ -29,7 +29,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
        return dev->ats && dev->ats->is_enabled;
 }
 
-#else /* CONFIG_PCI_IOV */
+#else /* CONFIG_PCI_ATS */
 
 static inline int pci_enable_ats(struct pci_dev *dev, int ps)
 {
@@ -50,7 +50,7 @@ static inline int pci_ats_enabled(struct pci_dev *dev)
        return 0;
 }
 
-#endif /* CONFIG_PCI_IOV */
+#endif /* CONFIG_PCI_ATS */
 
 #ifdef CONFIG_PCI_PRI
 
index 337df0d..7cda65b 100644 (file)
@@ -338,7 +338,7 @@ struct pci_dev {
        struct list_head msi_list;
 #endif
        struct pci_vpd *vpd;
-#ifdef CONFIG_PCI_IOV
+#ifdef CONFIG_PCI_ATS
        union {
                struct pci_sriov *sriov;        /* SR-IOV capability related */
                struct pci_dev *physfn; /* the PF this VF is associated with */
index 3fdf251..172ba70 100644 (file)
 
 #define PCI_VENDOR_ID_AZWAVE           0x1a3b
 
+#define PCI_VENDOR_ID_ASMEDIA          0x1b21
+
 #define PCI_VENDOR_ID_TEKRAM           0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290     0xdc29
 
index 3605e94..04c0110 100644 (file)
@@ -121,6 +121,7 @@ extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
 extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
 #else
 
+struct pinctrl_dev;
 
 /* Sufficiently stupid default function when pinctrl is not in use */
 static inline bool pin_is_valid(struct pinctrl_dev *pctldev, int pin)
index c533670..7281d5a 100644 (file)
@@ -30,7 +30,7 @@
  */
 
 struct tc_stats {
-       __u64   bytes;                  /* NUmber of enqueues bytes */
+       __u64   bytes;                  /* Number of enqueued bytes */
        __u32   packets;                /* Number of enqueued packets   */
        __u32   drops;                  /* Packets dropped because of lack of resources */
        __u32   overlimits;             /* Number of throttle events when this
@@ -297,7 +297,7 @@ struct tc_htb_glob {
        __u32 debug;            /* debug flags */
 
        /* stats */
-       __u32 direct_pkts; /* count of non shapped packets */
+       __u32 direct_pkts; /* count of non shaped packets */
 };
 enum {
        TCA_HTB_UNSPEC,
@@ -503,7 +503,7 @@ enum {
 };
 #define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1)
 
-/* State transition probablities for 4 state model */
+/* State transition probabilities for 4 state model */
 struct tc_netem_gimodel {
        __u32   p13;
        __u32   p31;
index f15acb6..3f3ed83 100644 (file)
@@ -54,118 +54,145 @@ typedef struct pm_message {
 /**
  * struct dev_pm_ops - device PM callbacks
  *
- * Several driver power state transitions are externally visible, affecting
+ * Several device power state transitions are externally visible, affecting
  * the state of pending I/O queues and (for drivers that touch hardware)
  * interrupts, wakeups, DMA, and other hardware state.  There may also be
- * internal transitions to various low power modes, which are transparent
+ * internal transitions to various low-power modes which are transparent
  * to the rest of the driver stack (such as a driver that's ON gating off
  * clocks which are not in active use).
  *
- * The externally visible transitions are handled with the help of the following
- * callbacks included in this structure:
- *
- * @prepare: Prepare the device for the upcoming transition, but do NOT change
- *     its hardware state.  Prevent new children of the device from being
- *     registered after @prepare() returns (the driver's subsystem and
- *     generally the rest of the kernel is supposed to prevent new calls to the
- *     probe method from being made too once @prepare() has succeeded).  If
- *     @prepare() detects a situation it cannot handle (e.g. registration of a
- *     child already in progress), it may return -EAGAIN, so that the PM core
- *     can execute it once again (e.g. after the new child has been registered)
- *     to recover from the race condition.  This method is executed for all
- *     kinds of suspend transitions and is followed by one of the suspend
- *     callbacks: @suspend(), @freeze(), or @poweroff().
- *     The PM core executes @prepare() for all devices before starting to
- *     execute suspend callbacks for any of them, so drivers may assume all of
- *     the other devices to be present and functional while @prepare() is being
- *     executed.  In particular, it is safe to make GFP_KERNEL memory
- *     allocations from within @prepare().  However, drivers may NOT assume
- *     anything about the availability of the user space at that time and it
- *     is not correct to request firmware from within @prepare() (it's too
- *     late to do that).  [To work around this limitation, drivers may
- *     register suspend and hibernation notifiers that are executed before the
- *     freezing of tasks.]
+ * The externally visible transitions are handled with the help of callbacks
+ * included in this structure in such a way that two levels of callbacks are
+ * involved.  First, the PM core executes callbacks provided by PM domains,
+ * device types, classes and bus types.  They are the subsystem-level callbacks
+ * supposed to execute callbacks provided by device drivers, although they may
+ * choose not to do that.  If the driver callbacks are executed, they have to
+ * collaborate with the subsystem-level callbacks to achieve the goals
+ * appropriate for the given system transition, given transition phase and the
+ * subsystem the device belongs to.
+ *
+ * @prepare: The principal role of this callback is to prevent new children of
+ *     the device from being registered after it has returned (the driver's
+ *     subsystem and generally the rest of the kernel is supposed to prevent
+ *     new calls to the probe method from being made too once @prepare() has
+ *     succeeded).  If @prepare() detects a situation it cannot handle (e.g.
+ *     registration of a child already in progress), it may return -EAGAIN, so
+ *     that the PM core can execute it once again (e.g. after a new child has
+ *     been registered) to recover from the race condition.
+ *     This method is executed for all kinds of suspend transitions and is
+ *     followed by one of the suspend callbacks: @suspend(), @freeze(), or
+ *     @poweroff().  The PM core executes subsystem-level @prepare() for all
+ *     devices before starting to invoke suspend callbacks for any of them, so
+ *     generally devices may be assumed to be functional or to respond to
+ *     runtime resume requests while @prepare() is being executed.  However,
+ *     device drivers may NOT assume anything about the availability of user
+ *     space at that time and it is NOT valid to request firmware from within
+ *     @prepare() (it's too late to do that).  It also is NOT valid to allocate
+ *     substantial amounts of memory from @prepare() in the GFP_KERNEL mode.
+ *     [To work around these limitations, drivers may register suspend and
+ *     hibernation notifiers to be executed before the freezing of tasks.]
  *
  * @complete: Undo the changes made by @prepare().  This method is executed for
  *     all kinds of resume transitions, following one of the resume callbacks:
  *     @resume(), @thaw(), @restore().  Also called if the state transition
- *     fails before the driver's suspend callback (@suspend(), @freeze(),
- *     @poweroff()) can be executed (e.g. if the suspend callback fails for one
+ *     fails before the driver's suspend callback: @suspend(), @freeze() or
+ *     @poweroff(), can be executed (e.g. if the suspend callback fails for one
  *     of the other devices that the PM core has unsuccessfully attempted to
  *     suspend earlier).
- *     The PM core executes @complete() after it has executed the appropriate
- *     resume callback for all devices.
+ *     The PM core executes subsystem-level @complete() after it has executed
+ *     the appropriate resume callbacks for all devices.
  *
  * @suspend: Executed before putting the system into a sleep state in which the
- *     contents of main memory are preserved.  Quiesce the device, put it into
- *     a low power state appropriate for the upcoming system state (such as
- *     PCI_D3hot), and enable wakeup events as appropriate.
+ *     contents of main memory are preserved.  The exact action to perform
+ *     depends on the device's subsystem (PM domain, device type, class or bus
+ *     type), but generally the device must be quiescent after subsystem-level
+ *     @suspend() has returned, so that it doesn't do any I/O or DMA.
+ *     Subsystem-level @suspend() is executed for all devices after invoking
+ *     subsystem-level @prepare() for all of them.
  *
  * @resume: Executed after waking the system up from a sleep state in which the
- *     contents of main memory were preserved.  Put the device into the
- *     appropriate state, according to the information saved in memory by the
- *     preceding @suspend().  The driver starts working again, responding to
- *     hardware events and software requests.  The hardware may have gone
- *     through a power-off reset, or it may have maintained state from the
- *     previous suspend() which the driver may rely on while resuming.  On most
- *     platforms, there are no restrictions on availability of resources like
- *     clocks during @resume().
+ *     contents of main memory were preserved.  The exact action to perform
+ *     depends on the device's subsystem, but generally the driver is expected
+ *     to start working again, responding to hardware events and software
+ *     requests (the device itself may be left in a low-power state, waiting
+ *     for a runtime resume to occur).  The state of the device at the time its
+ *     driver's @resume() callback is run depends on the platform and subsystem
+ *     the device belongs to.  On most platforms, there are no restrictions on
+ *     availability of resources like clocks during @resume().
+ *     Subsystem-level @resume() is executed for all devices after invoking
+ *     subsystem-level @resume_noirq() for all of them.
  *
  * @freeze: Hibernation-specific, executed before creating a hibernation image.
- *     Quiesce operations so that a consistent image can be created, but do NOT
- *     otherwise put the device into a low power device state and do NOT emit
- *     system wakeup events.  Save in main memory the device settings to be
- *     used by @restore() during the subsequent resume from hibernation or by
- *     the subsequent @thaw(), if the creation of the image or the restoration
- *     of main memory contents from it fails.
+ *     Analogous to @suspend(), but it should not enable the device to signal
+ *     wakeup events or change its power state.  The majority of subsystems
+ *     (with the notable exception of the PCI bus type) expect the driver-level
+ *     @freeze() to save the device settings in memory to be used by @restore()
+ *     during the subsequent resume from hibernation.
+ *     Subsystem-level @freeze() is executed for all devices after invoking
+ *     subsystem-level @prepare() for all of them.
  *
  * @thaw: Hibernation-specific, executed after creating a hibernation image OR
- *     if the creation of the image fails.  Also executed after a failing
+ *     if the creation of an image has failed.  Also executed after a failing
  *     attempt to restore the contents of main memory from such an image.
  *     Undo the changes made by the preceding @freeze(), so the device can be
  *     operated in the same way as immediately before the call to @freeze().
+ *     Subsystem-level @thaw() is executed for all devices after invoking
+ *     subsystem-level @thaw_noirq() for all of them.  It also may be executed
+ *     directly after @freeze() in case of a transition error.
  *
  * @poweroff: Hibernation-specific, executed after saving a hibernation image.
- *     Quiesce the device, put it into a low power state appropriate for the
- *     upcoming system state (such as PCI_D3hot), and enable wakeup events as
- *     appropriate.
+ *     Analogous to @suspend(), but it need not save the device's settings in
+ *     memory.
+ *     Subsystem-level @poweroff() is executed for all devices after invoking
+ *     subsystem-level @prepare() for all of them.
  *
  * @restore: Hibernation-specific, executed after restoring the contents of main
- *     memory from a hibernation image.  Driver starts working again,
- *     responding to hardware events and software requests.  Drivers may NOT
- *     make ANY assumptions about the hardware state right prior to @restore().
- *     On most platforms, there are no restrictions on availability of
- *     resources like clocks during @restore().
- *
- * @suspend_noirq: Complete the operations of ->suspend() by carrying out any
- *     actions required for suspending the device that need interrupts to be
- *     disabled
- *
- * @resume_noirq: Prepare for the execution of ->resume() by carrying out any
- *     actions required for resuming the device that need interrupts to be
- *     disabled
- *
- * @freeze_noirq: Complete the operations of ->freeze() by carrying out any
- *     actions required for freezing the device that need interrupts to be
- *     disabled
- *
- * @thaw_noirq: Prepare for the execution of ->thaw() by carrying out any
- *     actions required for thawing the device that need interrupts to be
- *     disabled
- *
- * @poweroff_noirq: Complete the operations of ->poweroff() by carrying out any
- *     actions required for handling the device that need interrupts to be
- *     disabled
- *
- * @restore_noirq: Prepare for the execution of ->restore() by carrying out any
- *     actions required for restoring the operations of the device that need
- *     interrupts to be disabled
+ *     memory from a hibernation image, analogous to @resume().
+ *
+ * @suspend_noirq: Complete the actions started by @suspend().  Carry out any
+ *     additional operations required for suspending the device that might be
+ *     racing with its driver's interrupt handler, which is guaranteed not to
+ *     run while @suspend_noirq() is being executed.
+ *     It generally is expected that the device will be in a low-power state
+ *     (appropriate for the target system sleep state) after subsystem-level
+ *     @suspend_noirq() has returned successfully.  If the device can generate
+ *     system wakeup signals and is enabled to wake up the system, it should be
+ *     configured to do so at that time.  However, depending on the platform
+ *     and device's subsystem, @suspend() may be allowed to put the device into
+ *     the low-power state and configure it to generate wakeup signals, in
+ *     which case it generally is not necessary to define @suspend_noirq().
+ *
+ * @resume_noirq: Prepare for the execution of @resume() by carrying out any
+ *     operations required for resuming the device that might be racing with
+ *     its driver's interrupt handler, which is guaranteed not to run while
+ *     @resume_noirq() is being executed.
+ *
+ * @freeze_noirq: Complete the actions started by @freeze().  Carry out any
+ *     additional operations required for freezing the device that might be
+ *     racing with its driver's interrupt handler, which is guaranteed not to
+ *     run while @freeze_noirq() is being executed.
+ *     The power state of the device should not be changed by either @freeze()
+ *     or @freeze_noirq() and it should not be configured to signal system
+ *     wakeup by any of these callbacks.
+ *
+ * @thaw_noirq: Prepare for the execution of @thaw() by carrying out any
+ *     operations required for thawing the device that might be racing with its
+ *     driver's interrupt handler, which is guaranteed not to run while
+ *     @thaw_noirq() is being executed.
+ *
+ * @poweroff_noirq: Complete the actions started by @poweroff().  Analogous to
+ *     @suspend_noirq(), but it need not save the device's settings in memory.
+ *
+ * @restore_noirq: Prepare for the execution of @restore() by carrying out any
+ *     operations required for thawing the device that might be racing with its
+ *     driver's interrupt handler, which is guaranteed not to run while
+ *     @restore_noirq() is being executed.  Analogous to @resume_noirq().
  *
  * All of the above callbacks, except for @complete(), return error codes.
  * However, the error codes returned by the resume operations, @resume(),
- * @thaw(), @restore(), @resume_noirq(), @thaw_noirq(), and @restore_noirq() do
+ * @thaw(), @restore(), @resume_noirq(), @thaw_noirq(), and @restore_noirq(), do
  * not cause the PM core to abort the resume transition during which they are
- * returned.  The error codes returned in that cases are only printed by the PM
+ * returned.  The error codes returned in those cases are only printed by the PM
  * core to the system logs for debugging purposes.  Still, it is recommended
  * that drivers only return error codes from their resume methods in case of an
  * unrecoverable failure (i.e. when the device being handled refuses to resume
@@ -174,31 +201,43 @@ typedef struct pm_message {
  * their children.
  *
  * It is allowed to unregister devices while the above callbacks are being
- * executed.  However, it is not allowed to unregister a device from within any
- * of its own callbacks.
+ * executed.  However, a callback routine must NOT try to unregister the device
+ * it was called for, although it may unregister children of that device (for
+ * example, if it detects that a child was unplugged while the system was
+ * asleep).
+ *
+ * Refer to Documentation/power/devices.txt for more information about the role
+ * of the above callbacks in the system suspend process.
  *
- * There also are the following callbacks related to run-time power management
- * of devices:
+ * There also are callbacks related to runtime power management of devices.
+ * Again, these callbacks are executed by the PM core only for subsystems
+ * (PM domains, device types, classes and bus types) and the subsystem-level
+ * callbacks are supposed to invoke the driver callbacks.  Moreover, the exact
+ * actions to be performed by a device driver's callbacks generally depend on
+ * the platform and subsystem the device belongs to.
  *
  * @runtime_suspend: Prepare the device for a condition in which it won't be
  *     able to communicate with the CPU(s) and RAM due to power management.
- *     This need not mean that the device should be put into a low power state.
+ *     This need not mean that the device should be put into a low-power state.
  *     For example, if the device is behind a link which is about to be turned
  *     off, the device may remain at full power.  If the device does go to low
- *     power and is capable of generating run-time wake-up events, remote
- *     wake-up (i.e., a hardware mechanism allowing the device to request a
- *     change of its power state via a wake-up event, such as PCI PME) should
- *     be enabled for it.
+ *     power and is capable of generating runtime wakeup events, remote wakeup
+ *     (i.e., a hardware mechanism allowing the device to request a change of
+ *     its power state via an interrupt) should be enabled for it.
  *
  * @runtime_resume: Put the device into the fully active state in response to a
- *     wake-up event generated by hardware or at the request of software.  If
- *     necessary, put the device into the full power state and restore its
+ *     wakeup event generated by hardware or at the request of software.  If
+ *     necessary, put the device into the full-power state and restore its
  *     registers, so that it is fully operational.
  *
- * @runtime_idle: Device appears to be inactive and it might be put into a low
- *     power state if all of the necessary conditions are satisfied.  Check
+ * @runtime_idle: Device appears to be inactive and it might be put into a
+ *     low-power state if all of the necessary conditions are satisfied.  Check
  *     these conditions and handle the device as appropriate, possibly queueing
  *     a suspend request for it.  The return value is ignored by the PM core.
+ *
+ * Refer to Documentation/power/runtime_pm.txt for more information about the
+ * role of the above callbacks in device runtime power management.
+ *
  */
 
 struct dev_pm_ops {
@@ -447,6 +486,7 @@ struct dev_pm_info {
        unsigned int            async_suspend:1;
        bool                    is_prepared:1;  /* Owned by the PM core */
        bool                    is_suspended:1; /* Ditto */
+       bool                    ignore_children:1;
        spinlock_t              lock;
 #ifdef CONFIG_PM_SLEEP
        struct list_head        entry;
@@ -464,7 +504,6 @@ struct dev_pm_info {
        atomic_t                usage_count;
        atomic_t                child_count;
        unsigned int            disable_depth:3;
-       unsigned int            ignore_children:1;
        unsigned int            idle_notification:1;
        unsigned int            request_pending:1;
        unsigned int            deferred_resume:1;
index d8d9036..d3085e7 100644 (file)
@@ -52,11 +52,6 @@ static inline bool pm_children_suspended(struct device *dev)
                || !atomic_read(&dev->power.child_count);
 }
 
-static inline void pm_suspend_ignore_children(struct device *dev, bool enable)
-{
-       dev->power.ignore_children = enable;
-}
-
 static inline void pm_runtime_get_noresume(struct device *dev)
 {
        atomic_inc(&dev->power.usage_count);
@@ -130,7 +125,6 @@ static inline void pm_runtime_allow(struct device *dev) {}
 static inline void pm_runtime_forbid(struct device *dev) {}
 
 static inline bool pm_children_suspended(struct device *dev) { return false; }
-static inline void pm_suspend_ignore_children(struct device *dev, bool en) {}
 static inline void pm_runtime_get_noresume(struct device *dev) {}
 static inline void pm_runtime_put_noidle(struct device *dev) {}
 static inline bool device_run_wake(struct device *dev) { return false; }
index ea56732..2ca8cde 100644 (file)
@@ -35,10 +35,12 @@ struct pstore_info {
        spinlock_t      buf_lock;       /* serialize access to 'buf' */
        char            *buf;
        size_t          bufsize;
+       struct mutex    read_mutex;     /* serialize open/read/close */
        int             (*open)(struct pstore_info *psi);
        int             (*close)(struct pstore_info *psi);
        ssize_t         (*read)(u64 *id, enum pstore_type_id *type,
-                       struct timespec *time, struct pstore_info *psi);
+                       struct timespec *time, char **buf,
+                       struct pstore_info *psi);
        int             (*write)(enum pstore_type_id type, u64 *id,
                        unsigned int part, size_t size, struct pstore_info *psi);
        int             (*erase)(enum pstore_type_id type, u64 id,
index 68daf4f..1c4f3e9 100644 (file)
@@ -1521,7 +1521,6 @@ struct task_struct {
 #ifdef CONFIG_FAULT_INJECTION
        int make_it_fail;
 #endif
-       struct prop_local_single dirties;
        /*
         * when (nr_dirtied >= nr_dirtied_pause), it's time to call
         * balance_dirty_pages() for some dirty throttling pause
index 97ff8e2..3d86517 100644 (file)
@@ -207,13 +207,15 @@ struct serial_icounter_struct {
 
 struct serial_rs485 {
        __u32   flags;                  /* RS485 feature flags */
-#define SER_RS485_ENABLED              (1 << 0)
-#define SER_RS485_RTS_ON_SEND          (1 << 1)
-#define SER_RS485_RTS_AFTER_SEND       (1 << 2)
-#define SER_RS485_RTS_BEFORE_SEND      (1 << 3)
+#define SER_RS485_ENABLED              (1 << 0)        /* If enabled */
+#define SER_RS485_RTS_ON_SEND          (1 << 1)        /* Logical level for
+                                                          RTS pin when
+                                                          sending */
+#define SER_RS485_RTS_AFTER_SEND       (1 << 2)        /* Logical level for
+                                                          RTS pin after sent*/
 #define SER_RS485_RX_DURING_TX         (1 << 4)
-       __u32   delay_rts_before_send;  /* Milliseconds */
-       __u32   delay_rts_after_send;   /* Milliseconds */
+       __u32   delay_rts_before_send;  /* Delay before send (milliseconds) */
+       __u32   delay_rts_after_send;   /* Delay after send (milliseconds) */
        __u32   padding[5];             /* Memory is cheap, new structs
                                           are a royal PITA .. */
 };
index 0efa1f1..369273a 100644 (file)
@@ -67,6 +67,7 @@ enum {
        SCIx_IRDA_REGTYPE,
        SCIx_SCIFA_REGTYPE,
        SCIx_SCIFB_REGTYPE,
+       SCIx_SH2_SCIF_FIFODATA_REGTYPE,
        SCIx_SH3_SCIF_REGTYPE,
        SCIx_SH4_SCIF_REGTYPE,
        SCIx_SH4_SCIF_NO_SCSPTR_REGTYPE,
index 3ccf186..a20831c 100644 (file)
@@ -52,7 +52,6 @@ struct clk {
 
        unsigned long           arch_flags;
        void                    *priv;
-       struct dentry           *dentry;
        struct clk_mapping      *mapping;
        struct cpufreq_frequency_table *freq_table;
        unsigned int            nr_freqs;
@@ -94,6 +93,9 @@ int clk_rate_table_find(struct clk *clk,
 long clk_rate_div_range_round(struct clk *clk, unsigned int div_min,
                              unsigned int div_max, unsigned long rate);
 
+long clk_rate_mult_range_round(struct clk *clk, unsigned int mult_min,
+                              unsigned int mult_max, unsigned long rate);
+
 long clk_round_parent(struct clk *clk, unsigned long target,
                      unsigned long *best_freq, unsigned long *parent_freq,
                      unsigned int div_min, unsigned int div_max);
index bc8c920..8446789 100644 (file)
@@ -104,4 +104,80 @@ struct pinmux_info {
 int register_pinmux(struct pinmux_info *pip);
 int unregister_pinmux(struct pinmux_info *pip);
 
+/* helper macro for port */
+#define PORT_1(fn, pfx, sfx) fn(pfx, sfx)
+
+#define PORT_10(fn, pfx, sfx) \
+       PORT_1(fn, pfx##0, sfx), PORT_1(fn, pfx##1, sfx),       \
+       PORT_1(fn, pfx##2, sfx), PORT_1(fn, pfx##3, sfx),       \
+       PORT_1(fn, pfx##4, sfx), PORT_1(fn, pfx##5, sfx),       \
+       PORT_1(fn, pfx##6, sfx), PORT_1(fn, pfx##7, sfx),       \
+       PORT_1(fn, pfx##8, sfx), PORT_1(fn, pfx##9, sfx)
+
+#define PORT_90(fn, pfx, sfx) \
+       PORT_10(fn, pfx##1, sfx), PORT_10(fn, pfx##2, sfx),     \
+       PORT_10(fn, pfx##3, sfx), PORT_10(fn, pfx##4, sfx),     \
+       PORT_10(fn, pfx##5, sfx), PORT_10(fn, pfx##6, sfx),     \
+       PORT_10(fn, pfx##7, sfx), PORT_10(fn, pfx##8, sfx),     \
+       PORT_10(fn, pfx##9, sfx)
+
+#define _PORT_ALL(pfx, sfx) pfx##_##sfx
+#define _GPIO_PORT(pfx, sfx) PINMUX_GPIO(GPIO_PORT##pfx, PORT##pfx##_DATA)
+#define PORT_ALL(str)  CPU_ALL_PORT(_PORT_ALL, PORT, str)
+#define GPIO_PORT_ALL()        CPU_ALL_PORT(_GPIO_PORT, , unused)
+#define GPIO_FN(str) PINMUX_GPIO(GPIO_FN_##str, str##_MARK)
+
+/* helper macro for pinmux_enum_t */
+#define PORT_DATA_I(nr)        \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_IN)
+
+#define PORT_DATA_I_PD(nr)     \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PD)
+
+#define PORT_DATA_I_PU(nr)     \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PU)
+
+#define PORT_DATA_I_PU_PD(nr)  \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0,                    \
+                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
+
+#define PORT_DATA_O(nr)                \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT)
+
+#define PORT_DATA_IO(nr)       \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,    \
+                   PORT##nr##_IN)
+
+#define PORT_DATA_IO_PD(nr)    \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PD)
+
+#define PORT_DATA_IO_PU(nr)    \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PU)
+
+#define PORT_DATA_IO_PU_PD(nr) \
+       PINMUX_DATA(PORT##nr##_DATA, PORT##nr##_FN0, PORT##nr##_OUT,    \
+                   PORT##nr##_IN, PORT##nr##_IN_PD, PORT##nr##_IN_PU)
+
+/* helper macro for top 4 bits in PORTnCR */
+#define _PCRH(in, in_pd, in_pu, out)   \
+       0, (out), (in), 0,              \
+       0, 0, 0, 0,                     \
+       0, 0, (in_pd), 0,               \
+       0, 0, (in_pu), 0
+
+#define PORTCR(nr, reg)                                                        \
+       {                                                               \
+               PINMUX_CFG_REG("PORT" nr "CR", reg, 8, 4) {             \
+                       _PCRH(PORT##nr##_IN, PORT##nr##_IN_PD,          \
+                             PORT##nr##_IN_PU, PORT##nr##_OUT),        \
+                               PORT##nr##_FN0, PORT##nr##_FN1,         \
+                               PORT##nr##_FN2, PORT##nr##_FN3,         \
+                               PORT##nr##_FN4, PORT##nr##_FN5,         \
+                               PORT##nr##_FN6, PORT##nr##_FN7 }        \
+       }
+
 #endif /* __SH_PFC_H */
index add4790..e9e72bd 100644 (file)
@@ -85,6 +85,8 @@
  * @reset: reset the device
  *     vdev: the virtio device
  *     After this, status and feature negotiation must be done again
+ *     Device must not be reset from its vq/config callbacks, or in
+ *     parallel with being added/removed.
  * @find_vqs: find virtqueues and instantiate them.
  *     vdev: the virtio_device
  *     nvqs: the number of virtqueues to find
index 27c7ede..5c7b6f0 100644 (file)
@@ -63,7 +63,7 @@
 #define VIRTIO_MMIO_GUEST_FEATURES     0x020
 
 /* Activated features set selector - Write Only */
-#define VIRTIO_MMIO_GUEST_FEATURES_SET 0x024
+#define VIRTIO_MMIO_GUEST_FEATURES_SEL 0x024
 
 /* Guest's memory page size in bytes - Write Only */
 #define VIRTIO_MMIO_GUEST_PAGE_SIZE    0x028
index 687fb11..4bde182 100644 (file)
@@ -119,7 +119,7 @@ unmap_kernel_range(unsigned long addr, unsigned long size)
 #endif
 
 /* Allocate/destroy a 'vmalloc' VM area. */
-extern struct vm_struct *alloc_vm_area(size_t size);
+extern struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes);
 extern void free_vm_area(struct vm_struct *area);
 
 /* for /dev/kmem */
index ab90ae0..6cc18f3 100644 (file)
 #define L2CAP_DEFAULT_ACK_TO           200
 #define L2CAP_LE_DEFAULT_MTU           23
 
-#define L2CAP_CONN_TIMEOUT     (40000) /* 40 seconds */
-#define L2CAP_INFO_TIMEOUT     (4000)  /*  4 seconds */
+#define L2CAP_DISC_TIMEOUT             (100)
+#define L2CAP_DISC_REJ_TIMEOUT         (5000)  /*  5 seconds */
+#define L2CAP_ENC_TIMEOUT              (5000)  /*  5 seconds */
+#define L2CAP_CONN_TIMEOUT             (40000) /* 40 seconds */
+#define L2CAP_INFO_TIMEOUT             (4000)  /*  4 seconds */
 
 /* L2CAP socket address */
 struct sockaddr_l2 {
index 92cf1c2..95852e3 100644 (file)
@@ -456,6 +456,9 @@ enum station_parameters_apply_mask {
  *     as the AC bitmap in the QoS info field
  * @max_sp: max Service Period. same format as the MAX_SP in the
  *     QoS info field (but already shifted down)
+ * @sta_modify_mask: bitmap indicating which parameters changed
+ *     (for those that don't have a natural "no change" value),
+ *     see &enum station_parameters_apply_mask
  */
 struct station_parameters {
        u8 *supported_rates;
@@ -615,6 +618,7 @@ struct sta_bss_parameters {
  *     user space MLME/SME implementation. The information is provided for
  *     the cfg80211_new_sta() calls to notify user space of the IEs.
  * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets.
+ * @sta_flags: station flags mask & values
  */
 struct station_info {
        u32 filled;
index 4fb6c43..6faec1a 100644 (file)
@@ -205,12 +205,7 @@ dst_feature(const struct dst_entry *dst, u32 feature)
 
 static inline u32 dst_mtu(const struct dst_entry *dst)
 {
-       u32 mtu = dst_metric_raw(dst, RTAX_MTU);
-
-       if (!mtu)
-               mtu = dst->ops->default_mtu(dst);
-
-       return mtu;
+       return dst->ops->mtu(dst);
 }
 
 /* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
index 9adb998..e1c2ee0 100644 (file)
@@ -17,7 +17,7 @@ struct dst_ops {
        int                     (*gc)(struct dst_ops *ops);
        struct dst_entry *      (*check)(struct dst_entry *, __u32 cookie);
        unsigned int            (*default_advmss)(const struct dst_entry *);
-       unsigned int            (*default_mtu)(const struct dst_entry *);
+       unsigned int            (*mtu)(const struct dst_entry *);
        u32 *                   (*cow_metrics)(struct dst_entry *, unsigned long);
        void                    (*destroy)(struct dst_entry *);
        void                    (*ifdown)(struct dst_entry *,
index b897d6e..f941964 100644 (file)
@@ -31,6 +31,7 @@
 /** struct ip_options - IP Options
  *
  * @faddr - Saved first hop address
+ * @nexthop - Saved nexthop address in LSRR and SSRR
  * @is_data - Options in __data, rather than skb
  * @is_strictroute - Strict source route
  * @srr_is_hit - Packet destination addr was our one
@@ -41,6 +42,7 @@
  */
 struct ip_options {
        __be32          faddr;
+       __be32          nexthop;
        unsigned char   optlen;
        unsigned char   srr;
        unsigned char   rr;
index 78c83e6..e9ff3fc 100644 (file)
@@ -35,6 +35,7 @@ struct inet_peer {
 
        u32                     metrics[RTAX_MAX];
        u32                     rate_tokens;    /* rate limiting for ICMP */
+       int                     redirect_genid;
        unsigned long           rate_last;
        unsigned long           pmtu_expires;
        u32                     pmtu_orig;
index 4283508..a88fb69 100644 (file)
@@ -67,18 +67,18 @@ struct nf_ct_event_notifier {
        int (*fcn)(unsigned int events, struct nf_ct_event *item);
 };
 
-extern struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
-extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
-extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
+extern int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *nb);
+extern void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb);
 
 extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
 
 static inline void
 nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
 {
+       struct net *net = nf_ct_net(ct);
        struct nf_conntrack_ecache *e;
 
-       if (nf_conntrack_event_cb == NULL)
+       if (net->ct.nf_conntrack_event_cb == NULL)
                return;
 
        e = nf_ct_ecache_find(ct);
@@ -95,11 +95,12 @@ nf_conntrack_eventmask_report(unsigned int eventmask,
                              int report)
 {
        int ret = 0;
+       struct net *net = nf_ct_net(ct);
        struct nf_ct_event_notifier *notify;
        struct nf_conntrack_ecache *e;
 
        rcu_read_lock();
-       notify = rcu_dereference(nf_conntrack_event_cb);
+       notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
        if (notify == NULL)
                goto out_unlock;
 
@@ -164,9 +165,8 @@ struct nf_exp_event_notifier {
        int (*fcn)(unsigned int events, struct nf_exp_event *item);
 };
 
-extern struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
-extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
-extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
+extern int nf_ct_expect_register_notifier(struct net *net, struct nf_exp_event_notifier *nb);
+extern void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb);
 
 static inline void
 nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
@@ -174,11 +174,12 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
                          u32 pid,
                          int report)
 {
+       struct net *net = nf_ct_exp_net(exp);
        struct nf_exp_event_notifier *notify;
        struct nf_conntrack_ecache *e;
 
        rcu_read_lock();
-       notify = rcu_dereference(nf_expect_event_cb);
+       notify = rcu_dereference(net->ct.nf_expect_event_cb);
        if (notify == NULL)
                goto out_unlock;
 
index 0249399..7a911ec 100644 (file)
@@ -18,6 +18,8 @@ struct netns_ct {
        struct hlist_nulls_head unconfirmed;
        struct hlist_nulls_head dying;
        struct ip_conntrack_stat __percpu *stat;
+       struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
+       struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
        int                     sysctl_events;
        unsigned int            sysctl_events_retry_timeout;
        int                     sysctl_acct;
index 3319f16..b72a3b8 100644 (file)
@@ -116,7 +116,7 @@ struct red_parms {
        u32             qR;             /* Cached random number */
 
        unsigned long   qavg;           /* Average queue length: A scaled */
-       psched_time_t   qidlestart;     /* Start of current idle period */
+       ktime_t         qidlestart;     /* Start of current idle period */
 };
 
 static inline u32 red_rmask(u8 Plog)
@@ -148,17 +148,17 @@ static inline void red_set_parms(struct red_parms *p,
 
 static inline int red_is_idling(struct red_parms *p)
 {
-       return p->qidlestart != PSCHED_PASTPERFECT;
+       return p->qidlestart.tv64 != 0;
 }
 
 static inline void red_start_of_idle_period(struct red_parms *p)
 {
-       p->qidlestart = psched_get_time();
+       p->qidlestart = ktime_get();
 }
 
 static inline void red_end_of_idle_period(struct red_parms *p)
 {
-       p->qidlestart = PSCHED_PASTPERFECT;
+       p->qidlestart.tv64 = 0;
 }
 
 static inline void red_restart(struct red_parms *p)
@@ -170,13 +170,10 @@ static inline void red_restart(struct red_parms *p)
 
 static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p)
 {
-       psched_time_t now;
-       long us_idle;
+       s64 delta = ktime_us_delta(ktime_get(), p->qidlestart);
+       long us_idle = min_t(s64, delta, p->Scell_max);
        int  shift;
 
-       now = psched_get_time();
-       us_idle = psched_tdiff_bounded(now, p->qidlestart, p->Scell_max);
-
        /*
         * The problem: ideally, average length queue recalcultion should
         * be done over constant clock intervals. This is too expensive, so
index db7b343..91855d1 100644 (file)
@@ -71,12 +71,12 @@ struct rtable {
        struct fib_info         *fi; /* for client ref to shared metrics */
 };
 
-static inline bool rt_is_input_route(struct rtable *rt)
+static inline bool rt_is_input_route(const struct rtable *rt)
 {
        return rt->rt_route_iif != 0;
 }
 
-static inline bool rt_is_output_route(struct rtable *rt)
+static inline bool rt_is_output_route(const struct rtable *rt)
 {
        return rt->rt_route_iif == 0;
 }
index b66ebb2..378c7ed 100644 (file)
@@ -307,15 +307,8 @@ struct omap_dss_board_info {
        void (*dsi_disable_pads)(int dsi_id, unsigned lane_mask);
 };
 
-#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS)
 /* Init with the board info */
 extern int omap_display_init(struct omap_dss_board_info *board_data);
-#else
-static inline int omap_display_init(struct omap_dss_board_info *board_data)
-{
-       return 0;
-}
-#endif
 
 struct omap_display_platform_data {
        struct omap_dss_board_info *board_data;
index a785a3b..438c256 100644 (file)
@@ -29,8 +29,7 @@
 static inline int xen_must_unplug_nics(void) {
 #if (defined(CONFIG_XEN_NETDEV_FRONTEND) || \
                defined(CONFIG_XEN_NETDEV_FRONTEND_MODULE)) && \
-               (defined(CONFIG_XEN_PLATFORM_PCI) || \
-                defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
+               defined(CONFIG_XEN_PVHVM)
         return 1;
 #else
         return 0;
@@ -40,8 +39,7 @@ static inline int xen_must_unplug_nics(void) {
 static inline int xen_must_unplug_disks(void) {
 #if (defined(CONFIG_XEN_BLKDEV_FRONTEND) || \
                defined(CONFIG_XEN_BLKDEV_FRONTEND_MODULE)) && \
-               (defined(CONFIG_XEN_PLATFORM_PCI) || \
-                defined(CONFIG_XEN_PLATFORM_PCI_MODULE))
+               defined(CONFIG_XEN_PVHVM)
         return 1;
 #else
         return 0;
index 5e828a2..213c035 100644 (file)
@@ -153,6 +153,13 @@ static void freezer_destroy(struct cgroup_subsys *ss,
        kfree(cgroup_freezer(cgroup));
 }
 
+/* task is frozen or will freeze immediately when next it gets woken */
+static bool is_task_frozen_enough(struct task_struct *task)
+{
+       return frozen(task) ||
+               (task_is_stopped_or_traced(task) && freezing(task));
+}
+
 /*
  * The call to cgroup_lock() in the freezer.state write method prevents
  * a write to that file racing against an attach, and hence the
@@ -231,7 +238,7 @@ static void update_if_frozen(struct cgroup *cgroup,
        cgroup_iter_start(cgroup, &it);
        while ((task = cgroup_iter_next(cgroup, &it))) {
                ntotal++;
-               if (frozen(task))
+               if (is_task_frozen_enough(task))
                        nfrozen++;
        }
 
@@ -284,7 +291,7 @@ static int try_to_freeze_cgroup(struct cgroup *cgroup, struct freezer *freezer)
        while ((task = cgroup_iter_next(cgroup, &it))) {
                if (!freeze_task(task, true))
                        continue;
-               if (frozen(task))
+               if (is_task_frozen_enough(task))
                        continue;
                if (!freezing(task) && !freezer_should_skip(task))
                        num_cant_freeze_now++;
index ba0d172..da4a6a1 100644 (file)
@@ -162,7 +162,6 @@ static void account_kernel_stack(struct thread_info *ti, int account)
 
 void free_task(struct task_struct *tsk)
 {
-       prop_local_destroy_single(&tsk->dirties);
        account_kernel_stack(tsk->stack, -1);
        free_thread_info(tsk->stack);
        rt_mutex_debug_task_free(tsk);
@@ -274,10 +273,6 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
 
        tsk->stack = ti;
 
-       err = prop_local_init_single(&tsk->dirties);
-       if (err)
-               goto out;
-
        setup_thread_stack(tsk, orig);
        clear_user_return_notifier(tsk);
        clear_tsk_need_resched(tsk);
index 422e567..ae34bf5 100644 (file)
@@ -885,10 +885,13 @@ static void __remove_hrtimer(struct hrtimer *timer,
                             struct hrtimer_clock_base *base,
                             unsigned long newstate, int reprogram)
 {
+       struct timerqueue_node *next_timer;
        if (!(timer->state & HRTIMER_STATE_ENQUEUED))
                goto out;
 
-       if (&timer->node == timerqueue_getnext(&base->active)) {
+       next_timer = timerqueue_getnext(&base->active);
+       timerqueue_del(&base->active, &timer->node);
+       if (&timer->node == next_timer) {
 #ifdef CONFIG_HIGH_RES_TIMERS
                /* Reprogram the clock event device. if enabled */
                if (reprogram && hrtimer_hres_active()) {
@@ -901,7 +904,6 @@ static void __remove_hrtimer(struct hrtimer *timer,
                }
 #endif
        }
-       timerqueue_del(&base->active, &timer->node);
        if (!timerqueue_getnext(&base->active))
                base->cpu_base->active_bases &= ~(1 << base->index);
 out:
index 67ce837..0e2b179 100644 (file)
@@ -1596,7 +1596,7 @@ int request_percpu_irq(unsigned int irq, irq_handler_t handler,
                return -ENOMEM;
 
        action->handler = handler;
-       action->flags = IRQF_PERCPU;
+       action->flags = IRQF_PERCPU | IRQF_NO_SUSPEND;
        action->name = devname;
        action->percpu_dev_id = dev_id;
 
index aa57d5d..dc813a9 100644 (file)
@@ -84,7 +84,9 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force)
         */
        action = desc->action;
        if (!action || !(action->flags & IRQF_SHARED) ||
-           (action->flags & __IRQF_TIMER) || !action->next)
+           (action->flags & __IRQF_TIMER) ||
+           (action->handler(irq, action->dev_id) == IRQ_HANDLED) ||
+           !action->next)
                goto out;
 
        /* Already running on another processor */
@@ -115,7 +117,7 @@ static int misrouted_irq(int irq)
        struct irq_desc *desc;
        int i, ok = 0;
 
-       if (atomic_inc_return(&irq_poll_active) == 1)
+       if (atomic_inc_return(&irq_poll_active) != 1)
                goto out;
 
        irq_poll_cpu = smp_processor_id();
index b4511b6..a6b0503 100644 (file)
@@ -55,6 +55,8 @@ enum {
 
 static int hibernation_mode = HIBERNATION_SHUTDOWN;
 
+static bool freezer_test_done;
+
 static const struct platform_hibernation_ops *hibernation_ops;
 
 /**
@@ -345,11 +347,24 @@ int hibernation_snapshot(int platform_mode)
 
        error = freeze_kernel_threads();
        if (error)
-               goto Close;
+               goto Cleanup;
+
+       if (hibernation_test(TEST_FREEZER) ||
+               hibernation_testmode(HIBERNATION_TESTPROC)) {
+
+               /*
+                * Indicate to the caller that we are returning due to a
+                * successful freezer test.
+                */
+               freezer_test_done = true;
+               goto Cleanup;
+       }
 
        error = dpm_prepare(PMSG_FREEZE);
-       if (error)
-               goto Complete_devices;
+       if (error) {
+               dpm_complete(msg);
+               goto Cleanup;
+       }
 
        suspend_console();
        pm_restrict_gfp_mask();
@@ -378,8 +393,6 @@ int hibernation_snapshot(int platform_mode)
                pm_restore_gfp_mask();
 
        resume_console();
-
- Complete_devices:
        dpm_complete(msg);
 
  Close:
@@ -389,6 +402,10 @@ int hibernation_snapshot(int platform_mode)
  Recover_platform:
        platform_recover(platform_mode);
        goto Resume_devices;
+
+ Cleanup:
+       swsusp_free();
+       goto Close;
 }
 
 /**
@@ -641,15 +658,13 @@ int hibernate(void)
        if (error)
                goto Finish;
 
-       if (hibernation_test(TEST_FREEZER))
-               goto Thaw;
-
-       if (hibernation_testmode(HIBERNATION_TESTPROC))
-               goto Thaw;
-
        error = hibernation_snapshot(hibernation_mode == HIBERNATION_PLATFORM);
        if (error)
                goto Thaw;
+       if (freezer_test_done) {
+               freezer_test_done = false;
+               goto Thaw;
+       }
 
        if (in_suspend) {
                unsigned int flags = 0;
index 71f49fe..36e0f09 100644 (file)
@@ -290,13 +290,14 @@ static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
                if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
                        break;
        }
-       if (state < PM_SUSPEND_MAX && *s)
+       if (state < PM_SUSPEND_MAX && *s) {
                error = enter_state(state);
                if (error) {
                        suspend_stats.fail++;
                        dpm_save_failed_errno(error);
                } else
                        suspend_stats.success++;
+       }
 #endif
 
  Exit:
index 56db751..995e3bd 100644 (file)
@@ -70,6 +70,7 @@ static struct pm_qos_constraints cpu_dma_constraints = {
 };
 static struct pm_qos_object cpu_dma_pm_qos = {
        .constraints = &cpu_dma_constraints,
+       .name = "cpu_dma_latency",
 };
 
 static BLOCKING_NOTIFIER_HEAD(network_lat_notifier);
index cf52fda..cfc65e1 100644 (file)
@@ -491,6 +491,22 @@ void clocksource_touch_watchdog(void)
        clocksource_resume_watchdog();
 }
 
+/**
+ * clocksource_max_adjustment- Returns max adjustment amount
+ * @cs:         Pointer to clocksource
+ *
+ */
+static u32 clocksource_max_adjustment(struct clocksource *cs)
+{
+       u64 ret;
+       /*
+        * We won't try to correct for more then 11% adjustments (110,000 ppm),
+        */
+       ret = (u64)cs->mult * 11;
+       do_div(ret,100);
+       return (u32)ret;
+}
+
 /**
  * clocksource_max_deferment - Returns max time the clocksource can be deferred
  * @cs:         Pointer to clocksource
@@ -503,25 +519,28 @@ static u64 clocksource_max_deferment(struct clocksource *cs)
        /*
         * Calculate the maximum number of cycles that we can pass to the
         * cyc2ns function without overflowing a 64-bit signed result. The
-        * maximum number of cycles is equal to ULLONG_MAX/cs->mult which
-        * is equivalent to the below.
-        * max_cycles < (2^63)/cs->mult
-        * max_cycles < 2^(log2((2^63)/cs->mult))
-        * max_cycles < 2^(log2(2^63) - log2(cs->mult))
-        * max_cycles < 2^(63 - log2(cs->mult))
-        * max_cycles < 1 << (63 - log2(cs->mult))
+        * maximum number of cycles is equal to ULLONG_MAX/(cs->mult+cs->maxadj)
+        * which is equivalent to the below.
+        * max_cycles < (2^63)/(cs->mult + cs->maxadj)
+        * max_cycles < 2^(log2((2^63)/(cs->mult + cs->maxadj)))
+        * max_cycles < 2^(log2(2^63) - log2(cs->mult + cs->maxadj))
+        * max_cycles < 2^(63 - log2(cs->mult + cs->maxadj))
+        * max_cycles < 1 << (63 - log2(cs->mult + cs->maxadj))
         * Please note that we add 1 to the result of the log2 to account for
         * any rounding errors, ensure the above inequality is satisfied and
         * no overflow will occur.
         */
-       max_cycles = 1ULL << (63 - (ilog2(cs->mult) + 1));
+       max_cycles = 1ULL << (63 - (ilog2(cs->mult + cs->maxadj) + 1));
 
        /*
         * The actual maximum number of cycles we can defer the clocksource is
         * determined by the minimum of max_cycles and cs->mask.
+        * Note: Here we subtract the maxadj to make sure we don't sleep for
+        * too long if there's a large negative adjustment.
         */
        max_cycles = min_t(u64, max_cycles, (u64) cs->mask);
-       max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult, cs->shift);
+       max_nsecs = clocksource_cyc2ns(max_cycles, cs->mult - cs->maxadj,
+                                       cs->shift);
 
        /*
         * To ensure that the clocksource does not wrap whilst we are idle,
@@ -640,7 +659,6 @@ static void clocksource_enqueue(struct clocksource *cs)
 void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq)
 {
        u64 sec;
-
        /*
         * Calc the maximum number of seconds which we can run before
         * wrapping around. For clocksources which have a mask > 32bit
@@ -661,6 +679,20 @@ void __clocksource_updatefreq_scale(struct clocksource *cs, u32 scale, u32 freq)
 
        clocks_calc_mult_shift(&cs->mult, &cs->shift, freq,
                               NSEC_PER_SEC / scale, sec * scale);
+
+       /*
+        * for clocksources that have large mults, to avoid overflow.
+        * Since mult may be adjusted by ntp, add an safety extra margin
+        *
+        */
+       cs->maxadj = clocksource_max_adjustment(cs);
+       while ((cs->mult + cs->maxadj < cs->mult)
+               || (cs->mult - cs->maxadj > cs->mult)) {
+               cs->mult >>= 1;
+               cs->shift--;
+               cs->maxadj = clocksource_max_adjustment(cs);
+       }
+
        cs->max_idle_ns = clocksource_max_deferment(cs);
 }
 EXPORT_SYMBOL_GPL(__clocksource_updatefreq_scale);
@@ -701,6 +733,12 @@ EXPORT_SYMBOL_GPL(__clocksource_register_scale);
  */
 int clocksource_register(struct clocksource *cs)
 {
+       /* calculate max adjustment for given mult/shift */
+       cs->maxadj = clocksource_max_adjustment(cs);
+       WARN_ONCE(cs->mult + cs->maxadj < cs->mult,
+               "Clocksource %s might overflow on 11%% adjustment\n",
+               cs->name);
+
        /* calculate max idle time permitted for this clocksource */
        cs->max_idle_ns = clocksource_max_deferment(cs);
 
index 2b021b0..2378413 100644 (file)
@@ -249,6 +249,8 @@ ktime_t ktime_get(void)
                secs = xtime.tv_sec + wall_to_monotonic.tv_sec;
                nsecs = xtime.tv_nsec + wall_to_monotonic.tv_nsec;
                nsecs += timekeeping_get_ns();
+               /* If arch requires, add in gettimeoffset() */
+               nsecs += arch_gettimeoffset();
 
        } while (read_seqretry(&xtime_lock, seq));
        /*
@@ -280,6 +282,8 @@ void ktime_get_ts(struct timespec *ts)
                *ts = xtime;
                tomono = wall_to_monotonic;
                nsecs = timekeeping_get_ns();
+               /* If arch requires, add in gettimeoffset() */
+               nsecs += arch_gettimeoffset();
 
        } while (read_seqretry(&xtime_lock, seq));
 
@@ -802,14 +806,44 @@ static void timekeeping_adjust(s64 offset)
        s64 error, interval = timekeeper.cycle_interval;
        int adj;
 
+       /*
+        * The point of this is to check if the error is greater then half
+        * an interval.
+        *
+        * First we shift it down from NTP_SHIFT to clocksource->shifted nsecs.
+        *
+        * Note we subtract one in the shift, so that error is really error*2.
+        * This "saves" dividing(shifting) intererval twice, but keeps the
+        * (error > interval) comparision as still measuring if error is
+        * larger then half an interval.
+        *
+        * Note: It does not "save" on aggrivation when reading the code.
+        */
        error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
        if (error > interval) {
+               /*
+                * We now divide error by 4(via shift), which checks if
+                * the error is greater then twice the interval.
+                * If it is greater, we need a bigadjust, if its smaller,
+                * we can adjust by 1.
+                */
                error >>= 2;
+               /*
+                * XXX - In update_wall_time, we round up to the next
+                * nanosecond, and store the amount rounded up into
+                * the error. This causes the likely below to be unlikely.
+                *
+                * The properfix is to avoid rounding up by using
+                * the high precision timekeeper.xtime_nsec instead of
+                * xtime.tv_nsec everywhere. Fixing this will take some
+                * time.
+                */
                if (likely(error <= interval))
                        adj = 1;
                else
                        adj = timekeeping_bigadjust(error, &interval, &offset);
        } else if (error < -interval) {
+               /* See comment above, this is just switched for the negative */
                error >>= 2;
                if (likely(error >= -interval)) {
                        adj = -1;
@@ -817,9 +851,65 @@ static void timekeeping_adjust(s64 offset)
                        offset = -offset;
                } else
                        adj = timekeeping_bigadjust(error, &interval, &offset);
-       } else
+       } else /* No adjustment needed */
                return;
 
+       WARN_ONCE(timekeeper.clock->maxadj &&
+                       (timekeeper.mult + adj > timekeeper.clock->mult +
+                                               timekeeper.clock->maxadj),
+                       "Adjusting %s more then 11%% (%ld vs %ld)\n",
+                       timekeeper.clock->name, (long)timekeeper.mult + adj,
+                       (long)timekeeper.clock->mult +
+                               timekeeper.clock->maxadj);
+       /*
+        * So the following can be confusing.
+        *
+        * To keep things simple, lets assume adj == 1 for now.
+        *
+        * When adj != 1, remember that the interval and offset values
+        * have been appropriately scaled so the math is the same.
+        *
+        * The basic idea here is that we're increasing the multiplier
+        * by one, this causes the xtime_interval to be incremented by
+        * one cycle_interval. This is because:
+        *      xtime_interval = cycle_interval * mult
+        * So if mult is being incremented by one:
+        *      xtime_interval = cycle_interval * (mult + 1)
+        * Its the same as:
+        *      xtime_interval = (cycle_interval * mult) + cycle_interval
+        * Which can be shortened to:
+        *      xtime_interval += cycle_interval
+        *
+        * So offset stores the non-accumulated cycles. Thus the current
+        * time (in shifted nanoseconds) is:
+        *      now = (offset * adj) + xtime_nsec
+        * Now, even though we're adjusting the clock frequency, we have
+        * to keep time consistent. In other words, we can't jump back
+        * in time, and we also want to avoid jumping forward in time.
+        *
+        * So given the same offset value, we need the time to be the same
+        * both before and after the freq adjustment.
+        *      now = (offset * adj_1) + xtime_nsec_1
+        *      now = (offset * adj_2) + xtime_nsec_2
+        * So:
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * adj_2) + xtime_nsec_2
+        * And we know:
+        *      adj_2 = adj_1 + 1
+        * So:
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * (adj_1+1)) + xtime_nsec_2
+        *      (offset * adj_1) + xtime_nsec_1 =
+        *              (offset * adj_1) + offset + xtime_nsec_2
+        * Canceling the sides:
+        *      xtime_nsec_1 = offset + xtime_nsec_2
+        * Which gives us:
+        *      xtime_nsec_2 = xtime_nsec_1 - offset
+        * Which simplfies to:
+        *      xtime_nsec -= offset
+        *
+        * XXX - TODO: Doc ntp_error calculation.
+        */
        timekeeper.mult += adj;
        timekeeper.xtime_interval += interval;
        timekeeper.xtime_nsec -= offset;
index a086064..71034f4 100644 (file)
@@ -724,6 +724,14 @@ void bdi_destroy(struct backing_dev_info *bdi)
 
        bdi_unregister(bdi);
 
+       /*
+        * If bdi_unregister() had already been called earlier, the
+        * wakeup_timer could still be armed because bdi_prune_sb()
+        * can race with the bdi_wakeup_thread_delayed() calls from
+        * __mark_inode_dirty().
+        */
+       del_timer_sync(&bdi->wb.wakeup_timer);
+
        for (i = 0; i < NR_BDI_STAT_ITEMS; i++)
                percpu_counter_destroy(&bdi->bdi_stat[i]);
 
index dae27ba..bb28a5f 100644 (file)
@@ -2422,6 +2422,8 @@ retry_avoidcopy:
         * anon_vma prepared.
         */
        if (unlikely(anon_vma_prepare(vma))) {
+               page_cache_release(new_page);
+               page_cache_release(old_page);
                /* Caller expects lock to be held */
                spin_lock(&mm->page_table_lock);
                return VM_FAULT_OOM;
index 73419c5..b982290 100644 (file)
@@ -454,7 +454,7 @@ void  __attribute__((weak)) vmalloc_sync_all(void)
  *     between processes, it syncs the pagetable across all
  *     processes.
  */
-struct vm_struct *alloc_vm_area(size_t size)
+struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes)
 {
        BUG();
        return NULL;
index 471dedb..76f2c5a 100644 (file)
@@ -185,6 +185,11 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
        if (!p)
                return 0;
 
+       if (p->signal->oom_score_adj == OOM_SCORE_ADJ_MIN) {
+               task_unlock(p);
+               return 0;
+       }
+
        /*
         * The memory controller may have a limit of 0 bytes, so avoid a divide
         * by zero, if necessary.
index a3278f0..7125248 100644 (file)
@@ -128,7 +128,6 @@ unsigned long global_dirty_limit;
  *
  */
 static struct prop_descriptor vm_completions;
-static struct prop_descriptor vm_dirties;
 
 /*
  * couple the period to the dirty_ratio:
@@ -154,7 +153,6 @@ static void update_completion_period(void)
 {
        int shift = calc_period_shift();
        prop_change_shift(&vm_completions, shift);
-       prop_change_shift(&vm_dirties, shift);
 
        writeback_set_ratelimit();
 }
@@ -235,11 +233,6 @@ void bdi_writeout_inc(struct backing_dev_info *bdi)
 }
 EXPORT_SYMBOL_GPL(bdi_writeout_inc);
 
-void task_dirty_inc(struct task_struct *tsk)
-{
-       prop_inc_single(&vm_dirties, &tsk->dirties);
-}
-
 /*
  * Obtain an accurate fraction of the BDI's portion.
  */
@@ -1133,17 +1126,17 @@ pause:
                                          pages_dirtied,
                                          pause,
                                          start_time);
-               __set_current_state(TASK_UNINTERRUPTIBLE);
+               __set_current_state(TASK_KILLABLE);
                io_schedule_timeout(pause);
 
-               dirty_thresh = hard_dirty_limit(dirty_thresh);
                /*
-                * max-pause area. If dirty exceeded but still within this
-                * area, no need to sleep for more than 200ms: (a) 8 pages per
-                * 200ms is typically more than enough to curb heavy dirtiers;
-                * (b) the pause time limit makes the dirtiers more responsive.
+                * This is typically equal to (nr_dirty < dirty_thresh) and can
+                * also keep "1000+ dd on a slow USB stick" under control.
                 */
-               if (nr_dirty < dirty_thresh)
+               if (task_ratelimit)
+                       break;
+
+               if (fatal_signal_pending(current))
                        break;
        }
 
@@ -1395,7 +1388,6 @@ void __init page_writeback_init(void)
 
        shift = calc_period_shift();
        prop_descriptor_init(&vm_completions, shift);
-       prop_descriptor_init(&vm_dirties, shift);
 }
 
 /**
@@ -1724,7 +1716,6 @@ void account_page_dirtied(struct page *page, struct address_space *mapping)
                __inc_zone_page_state(page, NR_DIRTIED);
                __inc_bdi_stat(mapping->backing_dev_info, BDI_RECLAIMABLE);
                __inc_bdi_stat(mapping->backing_dev_info, BDI_DIRTIED);
-               task_dirty_inc(current);
                task_io_account_write(PAGE_CACHE_SIZE);
        }
 }
index ea53496..12a48a8 100644 (file)
@@ -50,14 +50,13 @@ static struct page **pcpu_get_pages_and_bitmap(struct pcpu_chunk *chunk,
 
        if (!pages || !bitmap) {
                if (may_alloc && !pages)
-                       pages = pcpu_mem_alloc(pages_size);
+                       pages = pcpu_mem_zalloc(pages_size);
                if (may_alloc && !bitmap)
-                       bitmap = pcpu_mem_alloc(bitmap_size);
+                       bitmap = pcpu_mem_zalloc(bitmap_size);
                if (!pages || !bitmap)
                        return NULL;
        }
 
-       memset(pages, 0, pages_size);
        bitmap_copy(bitmap, chunk->populated, pcpu_unit_pages);
 
        *bitmapp = bitmap;
@@ -143,8 +142,8 @@ static void pcpu_pre_unmap_flush(struct pcpu_chunk *chunk,
                                 int page_start, int page_end)
 {
        flush_cache_vunmap(
-               pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
-               pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+               pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+               pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
 }
 
 static void __pcpu_unmap_pages(unsigned long addr, int nr_pages)
@@ -206,8 +205,8 @@ static void pcpu_post_unmap_tlb_flush(struct pcpu_chunk *chunk,
                                      int page_start, int page_end)
 {
        flush_tlb_kernel_range(
-               pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
-               pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+               pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+               pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
 }
 
 static int __pcpu_map_pages(unsigned long addr, struct page **pages,
@@ -284,8 +283,8 @@ static void pcpu_post_map_flush(struct pcpu_chunk *chunk,
                                int page_start, int page_end)
 {
        flush_cache_vmap(
-               pcpu_chunk_addr(chunk, pcpu_first_unit_cpu, page_start),
-               pcpu_chunk_addr(chunk, pcpu_last_unit_cpu, page_end));
+               pcpu_chunk_addr(chunk, pcpu_low_unit_cpu, page_start),
+               pcpu_chunk_addr(chunk, pcpu_high_unit_cpu, page_end));
 }
 
 /**
index bf80e55..3bb810a 100644 (file)
@@ -116,9 +116,9 @@ static int pcpu_atom_size __read_mostly;
 static int pcpu_nr_slots __read_mostly;
 static size_t pcpu_chunk_struct_size __read_mostly;
 
-/* cpus with the lowest and highest unit numbers */
-static unsigned int pcpu_first_unit_cpu __read_mostly;
-static unsigned int pcpu_last_unit_cpu __read_mostly;
+/* cpus with the lowest and highest unit addresses */
+static unsigned int pcpu_low_unit_cpu __read_mostly;
+static unsigned int pcpu_high_unit_cpu __read_mostly;
 
 /* the address of the first chunk which starts with the kernel static area */
 void *pcpu_base_addr __read_mostly;
@@ -273,11 +273,11 @@ static void __maybe_unused pcpu_next_pop(struct pcpu_chunk *chunk,
             (rs) = (re) + 1, pcpu_next_pop((chunk), &(rs), &(re), (end)))
 
 /**
- * pcpu_mem_alloc - allocate memory
+ * pcpu_mem_zalloc - allocate memory
  * @size: bytes to allocate
  *
  * Allocate @size bytes.  If @size is smaller than PAGE_SIZE,
- * kzalloc() is used; otherwise, vmalloc() is used.  The returned
+ * kzalloc() is used; otherwise, vzalloc() is used.  The returned
  * memory is always zeroed.
  *
  * CONTEXT:
@@ -286,7 +286,7 @@ static void __maybe_unused pcpu_next_pop(struct pcpu_chunk *chunk,
  * RETURNS:
  * Pointer to the allocated area on success, NULL on failure.
  */
-static void *pcpu_mem_alloc(size_t size)
+static void *pcpu_mem_zalloc(size_t size)
 {
        if (WARN_ON_ONCE(!slab_is_available()))
                return NULL;
@@ -302,7 +302,7 @@ static void *pcpu_mem_alloc(size_t size)
  * @ptr: memory to free
  * @size: size of the area
  *
- * Free @ptr.  @ptr should have been allocated using pcpu_mem_alloc().
+ * Free @ptr.  @ptr should have been allocated using pcpu_mem_zalloc().
  */
 static void pcpu_mem_free(void *ptr, size_t size)
 {
@@ -384,7 +384,7 @@ static int pcpu_extend_area_map(struct pcpu_chunk *chunk, int new_alloc)
        size_t old_size = 0, new_size = new_alloc * sizeof(new[0]);
        unsigned long flags;
 
-       new = pcpu_mem_alloc(new_size);
+       new = pcpu_mem_zalloc(new_size);
        if (!new)
                return -ENOMEM;
 
@@ -604,11 +604,12 @@ static struct pcpu_chunk *pcpu_alloc_chunk(void)
 {
        struct pcpu_chunk *chunk;
 
-       chunk = pcpu_mem_alloc(pcpu_chunk_struct_size);
+       chunk = pcpu_mem_zalloc(pcpu_chunk_struct_size);
        if (!chunk)
                return NULL;
 
-       chunk->map = pcpu_mem_alloc(PCPU_DFL_MAP_ALLOC * sizeof(chunk->map[0]));
+       chunk->map = pcpu_mem_zalloc(PCPU_DFL_MAP_ALLOC *
+                                               sizeof(chunk->map[0]));
        if (!chunk->map) {
                kfree(chunk);
                return NULL;
@@ -977,6 +978,17 @@ bool is_kernel_percpu_address(unsigned long addr)
  * address.  The caller is responsible for ensuring @addr stays valid
  * until this function finishes.
  *
+ * percpu allocator has special setup for the first chunk, which currently
+ * supports either embedding in linear address space or vmalloc mapping,
+ * and, from the second one, the backing allocator (currently either vm or
+ * km) provides translation.
+ *
+ * The addr can be tranlated simply without checking if it falls into the
+ * first chunk. But the current code reflects better how percpu allocator
+ * actually works, and the verification can discover both bugs in percpu
+ * allocator itself and per_cpu_ptr_to_phys() callers. So we keep current
+ * code.
+ *
  * RETURNS:
  * The physical address for @addr.
  */
@@ -984,19 +996,19 @@ phys_addr_t per_cpu_ptr_to_phys(void *addr)
 {
        void __percpu *base = __addr_to_pcpu_ptr(pcpu_base_addr);
        bool in_first_chunk = false;
-       unsigned long first_start, first_end;
+       unsigned long first_low, first_high;
        unsigned int cpu;
 
        /*
-        * The following test on first_start/end isn't strictly
+        * The following test on unit_low/high isn't strictly
         * necessary but will speed up lookups of addresses which
         * aren't in the first chunk.
         */
-       first_start = pcpu_chunk_addr(pcpu_first_chunk, pcpu_first_unit_cpu, 0);
-       first_end = pcpu_chunk_addr(pcpu_first_chunk, pcpu_last_unit_cpu,
-                                   pcpu_unit_pages);
-       if ((unsigned long)addr >= first_start &&
-           (unsigned long)addr < first_end) {
+       first_low = pcpu_chunk_addr(pcpu_first_chunk, pcpu_low_unit_cpu, 0);
+       first_high = pcpu_chunk_addr(pcpu_first_chunk, pcpu_high_unit_cpu,
+                                    pcpu_unit_pages);
+       if ((unsigned long)addr >= first_low &&
+           (unsigned long)addr < first_high) {
                for_each_possible_cpu(cpu) {
                        void *start = per_cpu_ptr(base, cpu);
 
@@ -1233,7 +1245,9 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
 
        for (cpu = 0; cpu < nr_cpu_ids; cpu++)
                unit_map[cpu] = UINT_MAX;
-       pcpu_first_unit_cpu = NR_CPUS;
+
+       pcpu_low_unit_cpu = NR_CPUS;
+       pcpu_high_unit_cpu = NR_CPUS;
 
        for (group = 0, unit = 0; group < ai->nr_groups; group++, unit += i) {
                const struct pcpu_group_info *gi = &ai->groups[group];
@@ -1253,9 +1267,13 @@ int __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai,
                        unit_map[cpu] = unit + i;
                        unit_off[cpu] = gi->base_offset + i * ai->unit_size;
 
-                       if (pcpu_first_unit_cpu == NR_CPUS)
-                               pcpu_first_unit_cpu = cpu;
-                       pcpu_last_unit_cpu = cpu;
+                       /* determine low/high unit_cpu */
+                       if (pcpu_low_unit_cpu == NR_CPUS ||
+                           unit_off[cpu] < unit_off[pcpu_low_unit_cpu])
+                               pcpu_low_unit_cpu = cpu;
+                       if (pcpu_high_unit_cpu == NR_CPUS ||
+                           unit_off[cpu] > unit_off[pcpu_high_unit_cpu])
+                               pcpu_high_unit_cpu = cpu;
                }
        }
        pcpu_nr_units = unit;
@@ -1889,7 +1907,7 @@ void __init percpu_init_late(void)
 
                BUILD_BUG_ON(size > PAGE_SIZE);
 
-               map = pcpu_mem_alloc(size);
+               map = pcpu_mem_zalloc(size);
                BUG_ON(!map);
 
                spin_lock_irqsave(&pcpu_lock, flags);
index 7d2a996..ed3334d 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1862,7 +1862,7 @@ static void unfreeze_partials(struct kmem_cache *s)
 {
        struct kmem_cache_node *n = NULL;
        struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab);
-       struct page *page;
+       struct page *page, *discard_page = NULL;
 
        while ((page = c->partial)) {
                enum slab_modes { M_PARTIAL, M_FREE };
@@ -1904,7 +1904,8 @@ static void unfreeze_partials(struct kmem_cache *s)
                                if (l == M_PARTIAL)
                                        remove_partial(n, page);
                                else
-                                       add_partial(n, page, 1);
+                                       add_partial(n, page,
+                                               DEACTIVATE_TO_TAIL);
 
                                l = m;
                        }
@@ -1915,14 +1916,22 @@ static void unfreeze_partials(struct kmem_cache *s)
                                "unfreezing slab"));
 
                if (m == M_FREE) {
-                       stat(s, DEACTIVATE_EMPTY);
-                       discard_slab(s, page);
-                       stat(s, FREE_SLAB);
+                       page->next = discard_page;
+                       discard_page = page;
                }
        }
 
        if (n)
                spin_unlock(&n->list_lock);
+
+       while (discard_page) {
+               page = discard_page;
+               discard_page = discard_page->next;
+
+               stat(s, DEACTIVATE_EMPTY);
+               discard_slab(s, page);
+               stat(s, FREE_SLAB);
+       }
 }
 
 /*
@@ -1969,7 +1978,7 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain)
                page->pobjects = pobjects;
                page->next = oldpage;
 
-       } while (this_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
+       } while (irqsafe_cpu_cmpxchg(s->cpu_slab->partial, oldpage, page) != oldpage);
        stat(s, CPU_PARTIAL_FREE);
        return pobjects;
 }
@@ -4435,30 +4444,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s,
 
                for_each_possible_cpu(cpu) {
                        struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu);
+                       int node = ACCESS_ONCE(c->node);
                        struct page *page;
 
-                       if (!c || c->node < 0)
+                       if (node < 0)
                                continue;
-
-                       if (c->page) {
-                                       if (flags & SO_TOTAL)
-                                               x = c->page->objects;
+                       page = ACCESS_ONCE(c->page);
+                       if (page) {
+                               if (flags & SO_TOTAL)
+                                       x = page->objects;
                                else if (flags & SO_OBJECTS)
-                                       x = c->page->inuse;
+                                       x = page->inuse;
                                else
                                        x = 1;
 
                                total += x;
-                               nodes[c->node] += x;
+                               nodes[node] += x;
                        }
                        page = c->partial;
 
                        if (page) {
                                x = page->pobjects;
-                                total += x;
-                                nodes[c->node] += x;
+                               total += x;
+                               nodes[node] += x;
                        }
-                       per_cpu[c->node]++;
+                       per_cpu[node]++;
                }
        }
 
index b669aa6..3231bf3 100644 (file)
@@ -2141,23 +2141,30 @@ void  __attribute__((weak)) vmalloc_sync_all(void)
 
 static int f(pte_t *pte, pgtable_t table, unsigned long addr, void *data)
 {
-       /* apply_to_page_range() does all the hard work. */
+       pte_t ***p = data;
+
+       if (p) {
+               *(*p) = pte;
+               (*p)++;
+       }
        return 0;
 }
 
 /**
  *     alloc_vm_area - allocate a range of kernel address space
  *     @size:          size of the area
+ *     @ptes:          returns the PTEs for the address space
  *
  *     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.
+ *     are created.
+ *
+ *     If @ptes is non-NULL, pointers to the PTEs (in init_mm)
+ *     allocated for the VM area are returned.
  */
-struct vm_struct *alloc_vm_area(size_t size)
+struct vm_struct *alloc_vm_area(size_t size, pte_t **ptes)
 {
        struct vm_struct *area;
 
@@ -2171,19 +2178,11 @@ struct vm_struct *alloc_vm_area(size_t size)
         * of kernel virtual address space and mapped into init_mm.
         */
        if (apply_to_page_range(&init_mm, (unsigned long)area->addr,
-                               area->size, f, NULL)) {
+                               size, f, ptes ? &ptes : NULL)) {
                free_vm_area(area);
                return NULL;
        }
 
-       /*
-        * If the allocated address space is passed to a hypercall
-        * before being used then we cannot rely on a page fault to
-        * trigger an update of the page tables.  So sync all the page
-        * tables here.
-        */
-       vmalloc_sync_all();
-
        return area;
 }
 EXPORT_SYMBOL_GPL(alloc_vm_area);
index c1c597e..e0af723 100644 (file)
@@ -673,7 +673,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
                goto encrypt;
 
 auth:
-       if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
+       if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
                return 0;
 
        if (!hci_conn_auth(conn, sec_level, auth_type))
index 8cd1291..5ea94a1 100644 (file)
@@ -251,7 +251,7 @@ static void l2cap_chan_timeout(unsigned long arg)
 
        if (sock_owned_by_user(sk)) {
                /* sk is owned by user. Try again later */
-               __set_chan_timer(chan, HZ / 5);
+               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                bh_unlock_sock(sk);
                chan_put(chan);
                return;
@@ -2488,7 +2488,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
                if (sock_owned_by_user(sk)) {
                        l2cap_state_change(chan, BT_DISCONN);
                        __clear_chan_timer(chan);
-                       __set_chan_timer(chan, HZ / 5);
+                       __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                        break;
                }
 
@@ -2661,7 +2661,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
 
        default:
                sk->sk_err = ECONNRESET;
-               __set_chan_timer(chan, HZ * 5);
+               __set_chan_timer(chan, L2CAP_DISC_REJ_TIMEOUT);
                l2cap_send_disconn_req(conn, chan, ECONNRESET);
                goto done;
        }
@@ -2718,7 +2718,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
        if (sock_owned_by_user(sk)) {
                l2cap_state_change(chan, BT_DISCONN);
                __clear_chan_timer(chan);
-               __set_chan_timer(chan, HZ / 5);
+               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                bh_unlock_sock(sk);
                return 0;
        }
@@ -2752,7 +2752,7 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
        if (sock_owned_by_user(sk)) {
                l2cap_state_change(chan,BT_DISCONN);
                __clear_chan_timer(chan);
-               __set_chan_timer(chan, HZ / 5);
+               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                bh_unlock_sock(sk);
                return 0;
        }
@@ -3998,7 +3998,7 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt)
        if (encrypt == 0x00) {
                if (chan->sec_level == BT_SECURITY_MEDIUM) {
                        __clear_chan_timer(chan);
-                       __set_chan_timer(chan, HZ * 5);
+                       __set_chan_timer(chan, L2CAP_ENC_TIMEOUT);
                } else if (chan->sec_level == BT_SECURITY_HIGH)
                        l2cap_chan_close(chan, ECONNREFUSED);
        } else {
@@ -4066,7 +4066,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                                        L2CAP_CONN_REQ, sizeof(req), &req);
                        } else {
                                __clear_chan_timer(chan);
-                               __set_chan_timer(chan, HZ / 10);
+                               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                        }
                } else if (chan->state == BT_CONNECT2) {
                        struct l2cap_conn_rsp rsp;
@@ -4086,7 +4086,7 @@ static int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
                                }
                        } else {
                                l2cap_state_change(chan, BT_DISCONN);
-                               __set_chan_timer(chan, HZ / 10);
+                               __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
                                res = L2CAP_CR_SEC_BLOCK;
                                stat = L2CAP_CS_NO_INFO;
                        }
index 995cbe0..a5f4e57 100644 (file)
@@ -1501,6 +1501,8 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
 
        __skb_pull(skb2, offset);
        skb_reset_transport_header(skb2);
+       skb_postpull_rcsum(skb2, skb_network_header(skb2),
+                          skb_network_header_len(skb2));
 
        icmp6_type = icmp6_hdr(skb2)->icmp6_type;
 
@@ -1770,7 +1772,7 @@ int br_multicast_toggle(struct net_bridge *br, unsigned long val)
        int err = 0;
        struct net_bridge_mdb_htable *mdb;
 
-       spin_lock(&br->multicast_lock);
+       spin_lock_bh(&br->multicast_lock);
        if (br->multicast_disabled == !val)
                goto unlock;
 
@@ -1806,7 +1808,7 @@ rollback:
        }
 
 unlock:
-       spin_unlock(&br->multicast_lock);
+       spin_unlock_bh(&br->multicast_lock);
 
        return err;
 }
index e5f9ece..a1daf82 100644 (file)
@@ -18,6 +18,7 @@
 #include <net/sock.h>
 
 #include "br_private.h"
+#include "br_private_stp.h"
 
 static inline size_t br_nlmsg_size(void)
 {
@@ -188,6 +189,11 @@ static int br_rtm_setlink(struct sk_buff *skb,  struct nlmsghdr *nlh, void *arg)
 
        p->state = new_state;
        br_log_state(p);
+
+       spin_lock_bh(&p->br->lock);
+       br_port_state_selection(p->br);
+       spin_unlock_bh(&p->br->lock);
+
        br_ifinfo_notify(RTM_NEWLINK, p);
 
        return 0;
index ad0a3f7..dd147d7 100644 (file)
@@ -399,25 +399,24 @@ void br_port_state_selection(struct net_bridge *br)
        struct net_bridge_port *p;
        unsigned int liveports = 0;
 
-       /* Don't change port states if userspace is handling STP */
-       if (br->stp_enabled == BR_USER_STP)
-               return;
-
        list_for_each_entry(p, &br->port_list, list) {
                if (p->state == BR_STATE_DISABLED)
                        continue;
 
-               if (p->port_no == br->root_port) {
-                       p->config_pending = 0;
-                       p->topology_change_ack = 0;
-                       br_make_forwarding(p);
-               } else if (br_is_designated_port(p)) {
-                       del_timer(&p->message_age_timer);
-                       br_make_forwarding(p);
-               } else {
-                       p->config_pending = 0;
-                       p->topology_change_ack = 0;
-                       br_make_blocking(p);
+               /* Don't change port states if userspace is handling STP */
+               if (br->stp_enabled != BR_USER_STP) {
+                       if (p->port_no == br->root_port) {
+                               p->config_pending = 0;
+                               p->topology_change_ack = 0;
+                               br_make_forwarding(p);
+                       } else if (br_is_designated_port(p)) {
+                               del_timer(&p->message_age_timer);
+                               br_make_forwarding(p);
+                       } else {
+                               p->config_pending = 0;
+                               p->topology_change_ack = 0;
+                               br_make_blocking(p);
+                       }
                }
 
                if (p->state == BR_STATE_FORWARDING)
index f399211..d3ca87b 100644 (file)
@@ -136,20 +136,21 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt)
 
 static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt)
 {
-       int tmp;
        u16 chks;
        u16 len;
+       __le16 data;
+
        struct cffrml *this = container_obj(layr);
        if (this->dofcs) {
                chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff);
-               tmp = cpu_to_le16(chks);
-               cfpkt_add_trail(pkt, &tmp, 2);
+               data = cpu_to_le16(chks);
+               cfpkt_add_trail(pkt, &data, 2);
        } else {
                cfpkt_pad_trail(pkt, 2);
        }
        len = cfpkt_getlen(pkt);
-       tmp = cpu_to_le16(len);
-       cfpkt_add_head(pkt, &tmp, 2);
+       data = cpu_to_le16(len);
+       cfpkt_add_head(pkt, &data, 2);
        cfpkt_info(pkt)->hdr_len += 2;
        if (cfpkt_erroneous(pkt)) {
                pr_err("Packet is erroneous!\n");
index 733e460..f4f3f58 100644 (file)
@@ -244,7 +244,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc,
                ceph_pagelist_init(req->r_trail);
        }
        /* create request message; allow space for oid */
-       msg_size += 40;
+       msg_size += MAX_OBJ_NAME_SIZE;
        if (snapc)
                msg_size += sizeof(u64) * snapc->num_snaps;
        if (use_mempool)
index 6ba50a1..5a13edf 100644 (file)
@@ -1396,7 +1396,7 @@ rollback:
        for_each_net(net) {
                for_each_netdev(net, dev) {
                        if (dev == last)
-                               break;
+                               goto outroll;
 
                        if (dev->flags & IFF_UP) {
                                nb->notifier_call(nb, NETDEV_GOING_DOWN, dev);
@@ -1407,6 +1407,7 @@ rollback:
                }
        }
 
+outroll:
        raw_notifier_chain_unregister(&netdev_chain, nb);
        goto unlock;
 }
@@ -4282,6 +4283,12 @@ static int dev_seq_open(struct inode *inode, struct file *file)
                            sizeof(struct dev_iter_state));
 }
 
+int dev_seq_open_ops(struct inode *inode, struct file *file,
+                    const struct seq_operations *ops)
+{
+       return seq_open_net(inode, file, ops, sizeof(struct dev_iter_state));
+}
+
 static const struct file_operations dev_seq_fops = {
        .owner   = THIS_MODULE,
        .open    = dev_seq_open,
index 277faef..febba51 100644 (file)
@@ -696,8 +696,7 @@ static const struct seq_operations dev_mc_seq_ops = {
 
 static int dev_mc_seq_open(struct inode *inode, struct file *file)
 {
-       return seq_open_net(inode, file, &dev_mc_seq_ops,
-                           sizeof(struct seq_net_private));
+       return dev_seq_open_ops(inode, file, &dev_mc_seq_ops);
 }
 
 static const struct file_operations dev_mc_seq_fops = {
index 039d51e..5ac07d3 100644 (file)
@@ -2397,7 +2397,10 @@ static struct pneigh_entry *pneigh_get_next(struct seq_file *seq,
        struct net *net = seq_file_net(seq);
        struct neigh_table *tbl = state->tbl;
 
-       pn = pn->next;
+       do {
+               pn = pn->next;
+       } while (pn && !net_eq(pneigh_net(pn), net));
+
        while (!pn) {
                if (++state->bucket > PNEIGH_HASHMASK)
                        break;
index 18a3ceb..3c30ee4 100644 (file)
@@ -2230,7 +2230,7 @@ static int skb_prepare_for_shift(struct sk_buff *skb)
  * @shiftlen: shift up to this many bytes
  *
  * Attempts to shift up to shiftlen worth of bytes, which may be less than
- * the length of the skb, from tgt to skb. Returns number bytes shifted.
+ * the length of the skb, from skb to tgt. Returns number bytes shifted.
  * It's up to caller to free skb if everything was shifted.
  *
  * If @tgt runs out of frags, the whole operation is aborted.
index 90a919a..3f4e541 100644 (file)
@@ -111,6 +111,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
                               inet->inet_sport, inet->inet_dport, sk);
        if (IS_ERR(rt)) {
+               err = PTR_ERR(rt);
                rt = NULL;
                goto failure;
        }
index a77d161..94f4ec0 100644 (file)
@@ -112,7 +112,7 @@ static unsigned long dn_rt_deadline;
 static int dn_dst_gc(struct dst_ops *ops);
 static struct dst_entry *dn_dst_check(struct dst_entry *, __u32);
 static unsigned int dn_dst_default_advmss(const struct dst_entry *dst);
-static unsigned int dn_dst_default_mtu(const struct dst_entry *dst);
+static unsigned int dn_dst_mtu(const struct dst_entry *dst);
 static void dn_dst_destroy(struct dst_entry *);
 static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
 static void dn_dst_link_failure(struct sk_buff *);
@@ -135,7 +135,7 @@ static struct dst_ops dn_dst_ops = {
        .gc =                   dn_dst_gc,
        .check =                dn_dst_check,
        .default_advmss =       dn_dst_default_advmss,
-       .default_mtu =          dn_dst_default_mtu,
+       .mtu =                  dn_dst_mtu,
        .cow_metrics =          dst_cow_metrics_generic,
        .destroy =              dn_dst_destroy,
        .negative_advice =      dn_dst_negative_advice,
@@ -825,9 +825,11 @@ static unsigned int dn_dst_default_advmss(const struct dst_entry *dst)
        return dn_mss_from_pmtu(dst->dev, dst_mtu(dst));
 }
 
-static unsigned int dn_dst_default_mtu(const struct dst_entry *dst)
+static unsigned int dn_dst_mtu(const struct dst_entry *dst)
 {
-       return dst->dev->mtu;
+       unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
+
+       return mtu ? : dst->dev->mtu;
 }
 
 static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
index 67f691b..d9c150c 100644 (file)
@@ -36,16 +36,13 @@ static void dn_slow_timer(unsigned long arg);
 
 void dn_start_slow_timer(struct sock *sk)
 {
-       sk->sk_timer.expires    = jiffies + SLOW_INTERVAL;
-       sk->sk_timer.function   = dn_slow_timer;
-       sk->sk_timer.data       = (unsigned long)sk;
-
-       add_timer(&sk->sk_timer);
+       setup_timer(&sk->sk_timer, dn_slow_timer, (unsigned long)sk);
+       sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL);
 }
 
 void dn_stop_slow_timer(struct sock *sk)
 {
-       del_timer(&sk->sk_timer);
+       sk_stop_timer(sk, &sk->sk_timer);
 }
 
 static void dn_slow_timer(unsigned long arg)
@@ -53,12 +50,10 @@ static void dn_slow_timer(unsigned long arg)
        struct sock *sk = (struct sock *)arg;
        struct dn_scp *scp = DN_SK(sk);
 
-       sock_hold(sk);
        bh_lock_sock(sk);
 
        if (sock_owned_by_user(sk)) {
-               sk->sk_timer.expires = jiffies + HZ / 10;
-               add_timer(&sk->sk_timer);
+               sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ / 10);
                goto out;
        }
 
@@ -100,9 +95,7 @@ static void dn_slow_timer(unsigned long arg)
                        scp->keepalive_fxn(sk);
        }
 
-       sk->sk_timer.expires = jiffies + SLOW_INTERVAL;
-
-       add_timer(&sk->sk_timer);
+       sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL);
 out:
        bh_unlock_sock(sk);
        sock_put(sk);
index c1f4154..36d1440 100644 (file)
@@ -136,8 +136,6 @@ static void ah_output_done(struct crypto_async_request *base, int err)
                memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr));
        }
 
-       err = ah->nexthdr;
-
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_output_resume(skb, err);
 }
@@ -264,12 +262,12 @@ static void ah_input_done(struct crypto_async_request *base, int err)
        if (err)
                goto out;
 
+       err = ah->nexthdr;
+
        skb->network_header += ah_hlen;
        memcpy(skb_network_header(skb), work_iph, ihl);
        __skb_pull(skb, ah_hlen + ihl);
        skb_set_transport_header(skb, -ihl);
-
-       err = ah->nexthdr;
 out:
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_input_resume(skb, err);
@@ -371,8 +369,6 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb)
                if (err == -EINPROGRESS)
                        goto out;
 
-               if (err == -EBUSY)
-                       err = NET_XMIT_DROP;
                goto out_free;
        }
 
index c6b5092..65f01dc 100644 (file)
@@ -1490,7 +1490,9 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
                             void __user *buffer,
                             size_t *lenp, loff_t *ppos)
 {
+       int old_value = *(int *)ctl->data;
        int ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+       int new_value = *(int *)ctl->data;
 
        if (write) {
                struct ipv4_devconf *cnf = ctl->extra1;
@@ -1501,6 +1503,9 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
 
                if (cnf == net->ipv4.devconf_dflt)
                        devinet_copy_dflt_conf(net, i);
+               if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1)
+                       if ((new_value == 0) && (old_value != 0))
+                               rt_cache_flush(net, 0);
        }
 
        return ret;
index c7472ef..b2ca095 100644 (file)
@@ -1716,7 +1716,8 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
        if (err) {
                int j;
 
-               pmc->sfcount[sfmode]--;
+               if (!delta)
+                       pmc->sfcount[sfmode]--;
                for (j=0; j<i; j++)
                        (void) ip_mc_del1_src(pmc, sfmode, &psfsrc[j]);
        } else if (isexclude != (pmc->sfcount[MCAST_EXCLUDE] != 0)) {
index f5e2bda..ccee270 100644 (file)
@@ -108,9 +108,6 @@ static int inet_csk_diag_fill(struct sock *sk,
                       icsk->icsk_ca_ops->name);
        }
 
-       if ((ext & (1 << (INET_DIAG_TOS - 1))) && (sk->sk_family != AF_INET6))
-               RTA_PUT_U8(skb, INET_DIAG_TOS, inet->tos);
-
        r->idiag_family = sk->sk_family;
        r->idiag_state = sk->sk_state;
        r->idiag_timer = 0;
@@ -125,16 +122,23 @@ static int inet_csk_diag_fill(struct sock *sk,
        r->id.idiag_src[0] = inet->inet_rcv_saddr;
        r->id.idiag_dst[0] = inet->inet_daddr;
 
+       /* IPv6 dual-stack sockets use inet->tos for IPv4 connections,
+        * hence this needs to be included regardless of socket family.
+        */
+       if (ext & (1 << (INET_DIAG_TOS - 1)))
+               RTA_PUT_U8(skb, INET_DIAG_TOS, inet->tos);
+
 #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
        if (r->idiag_family == AF_INET6) {
                const struct ipv6_pinfo *np = inet6_sk(sk);
 
+               if (ext & (1 << (INET_DIAG_TCLASS - 1)))
+                       RTA_PUT_U8(skb, INET_DIAG_TCLASS, np->tclass);
+
                ipv6_addr_copy((struct in6_addr *)r->id.idiag_src,
                               &np->rcv_saddr);
                ipv6_addr_copy((struct in6_addr *)r->id.idiag_dst,
                               &np->daddr);
-               if (ext & (1 << (INET_DIAG_TOS - 1)))
-                       RTA_PUT_U8(skb, INET_DIAG_TOS, np->tclass);
        }
 #endif
 
index 3b34d1c..29a07b6 100644 (file)
@@ -84,7 +84,7 @@ int ip_forward(struct sk_buff *skb)
 
        rt = skb_rtable(skb);
 
-       if (opt->is_strictroute && ip_hdr(skb)->daddr != rt->rt_gateway)
+       if (opt->is_strictroute && opt->nexthop != rt->rt_gateway)
                goto sr_failed;
 
        if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) &&
index ec93335..1e60f76 100644 (file)
@@ -568,12 +568,13 @@ void ip_forward_options(struct sk_buff *skb)
                     ) {
                        if (srrptr + 3 > srrspace)
                                break;
-                       if (memcmp(&ip_hdr(skb)->daddr, &optptr[srrptr-1], 4) == 0)
+                       if (memcmp(&opt->nexthop, &optptr[srrptr-1], 4) == 0)
                                break;
                }
                if (srrptr + 3 <= srrspace) {
                        opt->is_changed = 1;
                        ip_rt_get_source(&optptr[srrptr-1], skb, rt);
+                       ip_hdr(skb)->daddr = opt->nexthop;
                        optptr[2] = srrptr+4;
                } else if (net_ratelimit())
                        printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n");
@@ -640,6 +641,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
        }
        if (srrptr <= srrspace) {
                opt->srr_is_hit = 1;
+               opt->nexthop = nexthop;
                opt->is_changed = 1;
        }
        return 0;
index 9899619..4f47e06 100644 (file)
@@ -64,7 +64,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
        /* Change in oif may mean change in hh_len. */
        hh_len = skb_dst(skb)->dev->hard_header_len;
        if (skb_headroom(skb) < hh_len &&
-           pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
+           pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
+                               0, GFP_ATOMIC))
                return -1;
 
        return 0;
index 1dfc18a..f19f218 100644 (file)
@@ -325,7 +325,6 @@ config IP_NF_TARGET_TTL
 # raw + specific targets
 config IP_NF_RAW
        tristate  'raw table support (required for NOTRACK/TRACE)'
-       depends on NETFILTER_ADVANCED
        help
          This option adds a `raw' table to iptables. This table is the very
          first in the netfilter framework and hooks in at the PREROUTING
index a06f73f..43d4c3b 100644 (file)
@@ -339,7 +339,6 @@ void ping_err(struct sk_buff *skb, u32 info)
        sk = ping_v4_lookup(net, iph->daddr, iph->saddr,
                            ntohs(icmph->un.echo.id), skb->dev->ifindex);
        if (sk == NULL) {
-               ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS);
                pr_debug("no socket, dropping\n");
                return; /* No socket for error */
        }
@@ -679,7 +678,6 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n",
                inet_sk(sk), inet_sk(sk)->inet_num, skb);
        if (sock_queue_rcv_skb(sk, skb) < 0) {
-               ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_INERRORS);
                kfree_skb(skb);
                pr_debug("ping_queue_rcv_skb -> failed\n");
                return -1;
index 155138d..ca5e237 100644 (file)
@@ -131,6 +131,7 @@ static int ip_rt_mtu_expires __read_mostly  = 10 * 60 * HZ;
 static int ip_rt_min_pmtu __read_mostly                = 512 + 20 + 20;
 static int ip_rt_min_advmss __read_mostly      = 256;
 static int rt_chain_length_max __read_mostly   = 20;
+static int redirect_genid;
 
 /*
  *     Interface to generic destination cache.
@@ -138,7 +139,7 @@ static int rt_chain_length_max __read_mostly        = 20;
 
 static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
 static unsigned int     ipv4_default_advmss(const struct dst_entry *dst);
-static unsigned int     ipv4_default_mtu(const struct dst_entry *dst);
+static unsigned int     ipv4_mtu(const struct dst_entry *dst);
 static void             ipv4_dst_destroy(struct dst_entry *dst);
 static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
 static void             ipv4_link_failure(struct sk_buff *skb);
@@ -193,7 +194,7 @@ static struct dst_ops ipv4_dst_ops = {
        .gc =                   rt_garbage_collect,
        .check =                ipv4_dst_check,
        .default_advmss =       ipv4_default_advmss,
-       .default_mtu =          ipv4_default_mtu,
+       .mtu =                  ipv4_mtu,
        .cow_metrics =          ipv4_cow_metrics,
        .destroy =              ipv4_dst_destroy,
        .ifdown =               ipv4_dst_ifdown,
@@ -416,9 +417,13 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
        else {
                struct rtable *r = v;
                struct neighbour *n;
-               int len;
+               int len, HHUptod;
 
+               rcu_read_lock();
                n = dst_get_neighbour(&r->dst);
+               HHUptod = (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0;
+               rcu_read_unlock();
+
                seq_printf(seq, "%s\t%08X\t%08X\t%8X\t%d\t%u\t%d\t"
                              "%08X\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X%n",
                        r->dst.dev ? r->dst.dev->name : "*",
@@ -432,7 +437,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v)
                              dst_metric(&r->dst, RTAX_RTTVAR)),
                        r->rt_key_tos,
                        -1,
-                       (n && (n->nud_state & NUD_CONNECTED)) ? 1 : 0,
+                       HHUptod,
                        r->rt_spec_dst, &len);
 
                seq_printf(seq, "%*s\n", 127 - len, "");
@@ -837,6 +842,7 @@ static void rt_cache_invalidate(struct net *net)
 
        get_random_bytes(&shuffle, sizeof(shuffle));
        atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
+       redirect_genid++;
 }
 
 /*
@@ -1304,16 +1310,42 @@ static void rt_del(unsigned hash, struct rtable *rt)
        spin_unlock_bh(rt_hash_lock_addr(hash));
 }
 
+static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
+{
+       struct rtable *rt = (struct rtable *) dst;
+       __be32 orig_gw = rt->rt_gateway;
+       struct neighbour *n, *old_n;
+
+       dst_confirm(&rt->dst);
+
+       rt->rt_gateway = peer->redirect_learned.a4;
+
+       n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
+       if (IS_ERR(n))
+               return PTR_ERR(n);
+       old_n = xchg(&rt->dst._neighbour, n);
+       if (old_n)
+               neigh_release(old_n);
+       if (!n || !(n->nud_state & NUD_VALID)) {
+               if (n)
+                       neigh_event_send(n, NULL);
+               rt->rt_gateway = orig_gw;
+               return -EAGAIN;
+       } else {
+               rt->rt_flags |= RTCF_REDIRECTED;
+               call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
+       }
+       return 0;
+}
+
 /* called in rcu_read_lock() section */
 void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                    __be32 saddr, struct net_device *dev)
 {
        int s, i;
        struct in_device *in_dev = __in_dev_get_rcu(dev);
-       struct rtable *rt;
        __be32 skeys[2] = { saddr, 0 };
        int    ikeys[2] = { dev->ifindex, 0 };
-       struct flowi4 fl4;
        struct inet_peer *peer;
        struct net *net;
 
@@ -1336,33 +1368,44 @@ void ip_rt_redirect(__be32 old_gw, __be32 daddr, __be32 new_gw,
                        goto reject_redirect;
        }
 
-       memset(&fl4, 0, sizeof(fl4));
-       fl4.daddr = daddr;
        for (s = 0; s < 2; s++) {
                for (i = 0; i < 2; i++) {
-                       fl4.flowi4_oif = ikeys[i];
-                       fl4.saddr = skeys[s];
-                       rt = __ip_route_output_key(net, &fl4);
-                       if (IS_ERR(rt))
-                               continue;
-
-                       if (rt->dst.error || rt->dst.dev != dev ||
-                           rt->rt_gateway != old_gw) {
-                               ip_rt_put(rt);
-                               continue;
-                       }
-
-                       if (!rt->peer)
-                               rt_bind_peer(rt, rt->rt_dst, 1);
+                       unsigned int hash;
+                       struct rtable __rcu **rthp;
+                       struct rtable *rt;
+
+                       hash = rt_hash(daddr, skeys[s], ikeys[i], rt_genid(net));
+
+                       rthp = &rt_hash_table[hash].chain;
+
+                       while ((rt = rcu_dereference(*rthp)) != NULL) {
+                               rthp = &rt->dst.rt_next;
+
+                               if (rt->rt_key_dst != daddr ||
+                                   rt->rt_key_src != skeys[s] ||
+                                   rt->rt_oif != ikeys[i] ||
+                                   rt_is_input_route(rt) ||
+                                   rt_is_expired(rt) ||
+                                   !net_eq(dev_net(rt->dst.dev), net) ||
+                                   rt->dst.error ||
+                                   rt->dst.dev != dev ||
+                                   rt->rt_gateway != old_gw)
+                                       continue;
 
-                       peer = rt->peer;
-                       if (peer) {
-                               peer->redirect_learned.a4 = new_gw;
-                               atomic_inc(&__rt_peer_genid);
+                               if (!rt->peer)
+                                       rt_bind_peer(rt, rt->rt_dst, 1);
+
+                               peer = rt->peer;
+                               if (peer) {
+                                       if (peer->redirect_learned.a4 != new_gw ||
+                                           peer->redirect_genid != redirect_genid) {
+                                               peer->redirect_learned.a4 = new_gw;
+                                               peer->redirect_genid = redirect_genid;
+                                               atomic_inc(&__rt_peer_genid);
+                                       }
+                                       check_peer_redir(&rt->dst, peer);
+                               }
                        }
-
-                       ip_rt_put(rt);
-                       return;
                }
        }
        return;
@@ -1649,40 +1692,9 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu)
        }
 }
 
-static int check_peer_redir(struct dst_entry *dst, struct inet_peer *peer)
-{
-       struct rtable *rt = (struct rtable *) dst;
-       __be32 orig_gw = rt->rt_gateway;
-       struct neighbour *n, *old_n;
-
-       dst_confirm(&rt->dst);
-
-       rt->rt_gateway = peer->redirect_learned.a4;
-
-       n = ipv4_neigh_lookup(&rt->dst, &rt->rt_gateway);
-       if (IS_ERR(n))
-               return PTR_ERR(n);
-       old_n = xchg(&rt->dst._neighbour, n);
-       if (old_n)
-               neigh_release(old_n);
-       if (!n || !(n->nud_state & NUD_VALID)) {
-               if (n)
-                       neigh_event_send(n, NULL);
-               rt->rt_gateway = orig_gw;
-               return -EAGAIN;
-       } else {
-               rt->rt_flags |= RTCF_REDIRECTED;
-               call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, n);
-       }
-       return 0;
-}
 
-static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
+static struct rtable *ipv4_validate_peer(struct rtable *rt)
 {
-       struct rtable *rt = (struct rtable *) dst;
-
-       if (rt_is_expired(rt))
-               return NULL;
        if (rt->rt_peer_genid != rt_peer_genid()) {
                struct inet_peer *peer;
 
@@ -1691,17 +1703,29 @@ static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 
                peer = rt->peer;
                if (peer) {
-                       check_peer_pmtu(dst, peer);
+                       check_peer_pmtu(&rt->dst, peer);
 
+                       if (peer->redirect_genid != redirect_genid)
+                               peer->redirect_learned.a4 = 0;
                        if (peer->redirect_learned.a4 &&
                            peer->redirect_learned.a4 != rt->rt_gateway) {
-                               if (check_peer_redir(dst, peer))
+                               if (check_peer_redir(&rt->dst, peer))
                                        return NULL;
                        }
                }
 
                rt->rt_peer_genid = rt_peer_genid();
        }
+       return rt;
+}
+
+static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
+{
+       struct rtable *rt = (struct rtable *) dst;
+
+       if (rt_is_expired(rt))
+               return NULL;
+       dst = (struct dst_entry *) ipv4_validate_peer(rt);
        return dst;
 }
 
@@ -1806,12 +1830,17 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
        return advmss;
 }
 
-static unsigned int ipv4_default_mtu(const struct dst_entry *dst)
+static unsigned int ipv4_mtu(const struct dst_entry *dst)
 {
-       unsigned int mtu = dst->dev->mtu;
+       const struct rtable *rt = (const struct rtable *) dst;
+       unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
+
+       if (mtu && rt_is_output_route(rt))
+               return mtu;
+
+       mtu = dst->dev->mtu;
 
        if (unlikely(dst_metric_locked(dst, RTAX_MTU))) {
-               const struct rtable *rt = (const struct rtable *) dst;
 
                if (rt->rt_gateway != rt->rt_dst && mtu > 576)
                        mtu = 576;
@@ -1844,6 +1873,8 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4,
                dst_init_metrics(&rt->dst, peer->metrics, false);
 
                check_peer_pmtu(&rt->dst, peer);
+               if (peer->redirect_genid != redirect_genid)
+                       peer->redirect_learned.a4 = 0;
                if (peer->redirect_learned.a4 &&
                    peer->redirect_learned.a4 != rt->rt_gateway) {
                        rt->rt_gateway = peer->redirect_learned.a4;
@@ -2349,6 +2380,9 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr,
                    rth->rt_mark == skb->mark &&
                    net_eq(dev_net(rth->dst.dev), net) &&
                    !rt_is_expired(rth)) {
+                       rth = ipv4_validate_peer(rth);
+                       if (!rth)
+                               continue;
                        if (noref) {
                                dst_use_noref(&rth->dst, jiffies);
                                skb_dst_set_noref(skb, &rth->dst);
@@ -2724,6 +2758,9 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4)
                            (IPTOS_RT_MASK | RTO_ONLINK)) &&
                    net_eq(dev_net(rth->dst.dev), net) &&
                    !rt_is_expired(rth)) {
+                       rth = ipv4_validate_peer(rth);
+                       if (!rth)
+                               continue;
                        dst_use(&rth->dst, jiffies);
                        RT_CACHE_STAT_INC(out_hit);
                        rcu_read_unlock_bh();
@@ -2747,9 +2784,11 @@ static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 coo
        return NULL;
 }
 
-static unsigned int ipv4_blackhole_default_mtu(const struct dst_entry *dst)
+static unsigned int ipv4_blackhole_mtu(const struct dst_entry *dst)
 {
-       return 0;
+       unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
+
+       return mtu ? : dst->dev->mtu;
 }
 
 static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -2767,7 +2806,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
        .protocol               =       cpu_to_be16(ETH_P_IP),
        .destroy                =       ipv4_dst_destroy,
        .check                  =       ipv4_blackhole_dst_check,
-       .default_mtu            =       ipv4_blackhole_default_mtu,
+       .mtu                    =       ipv4_blackhole_mtu,
        .default_advmss         =       ipv4_default_advmss,
        .update_pmtu            =       ipv4_rt_blackhole_update_pmtu,
        .cow_metrics            =       ipv4_rt_blackhole_cow_metrics,
@@ -2845,7 +2884,7 @@ static int rt_fill_info(struct net *net,
        struct rtable *rt = skb_rtable(skb);
        struct rtmsg *r;
        struct nlmsghdr *nlh;
-       long expires = 0;
+       unsigned long expires = 0;
        const struct inet_peer *peer = rt->peer;
        u32 id = 0, ts = 0, tsage = 0, error;
 
@@ -2902,8 +2941,12 @@ static int rt_fill_info(struct net *net,
                        tsage = get_seconds() - peer->tcp_ts_stamp;
                }
                expires = ACCESS_ONCE(peer->pmtu_expires);
-               if (expires)
-                       expires -= jiffies;
+               if (expires) {
+                       if (time_before(jiffies, expires))
+                               expires -= jiffies;
+                       else
+                               expires = 0;
+               }
        }
 
        if (rt_is_input_route(rt)) {
index a744315..a9db4b1 100644 (file)
@@ -1510,6 +1510,7 @@ exit:
        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
        return NULL;
 put_and_exit:
+       tcp_clear_xmit_timers(newsk);
        bh_unlock_sock(newsk);
        sock_put(newsk);
        goto exit;
index 980b98f..63170e2 100644 (file)
@@ -1382,7 +1382,7 @@ static inline int tcp_minshall_check(const struct tcp_sock *tp)
 /* Return 0, if packet can be sent now without violation Nagle's rules:
  * 1. It is full sized.
  * 2. Or it contains FIN. (already checked by caller)
- * 3. Or TCP_NODELAY was set.
+ * 3. Or TCP_CORK is not set, and TCP_NODELAY is set.
  * 4. Or TCP_CORK is not set, and all sent packets are ACKed.
  *    With Minshall's modification: all sent small packets are ACKed.
  */
index ab0966d..5a65eea 100644 (file)
@@ -1164,7 +1164,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        struct inet_sock *inet = inet_sk(sk);
        struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
        struct sk_buff *skb;
-       unsigned int ulen;
+       unsigned int ulen, copied;
        int peeked;
        int err;
        int is_udplite = IS_UDPLITE(sk);
@@ -1186,9 +1186,10 @@ try_again:
                goto out;
 
        ulen = skb->len - sizeof(struct udphdr);
-       if (len > ulen)
-               len = ulen;
-       else if (len < ulen)
+       copied = len;
+       if (copied > ulen)
+               copied = ulen;
+       else if (copied < ulen)
                msg->msg_flags |= MSG_TRUNC;
 
        /*
@@ -1197,14 +1198,14 @@ try_again:
         * coverage checksum (UDP-Lite), do it before the copy.
         */
 
-       if (len < ulen || UDP_SKB_CB(skb)->partial_cov) {
+       if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
                if (udp_lib_checksum_complete(skb))
                        goto csum_copy_err;
        }
 
        if (skb_csum_unnecessary(skb))
                err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
-                                             msg->msg_iov, len);
+                                             msg->msg_iov, copied);
        else {
                err = skb_copy_and_csum_datagram_iovec(skb,
                                                       sizeof(struct udphdr),
@@ -1233,7 +1234,7 @@ try_again:
        if (inet->cmsg_flags)
                ip_cmsg_recv(msg, skb);
 
-       err = len;
+       err = copied;
        if (flags & MSG_TRUNC)
                err = ulen;
 
index 2195ae6..4c0f894 100644 (file)
@@ -324,8 +324,6 @@ static void ah6_output_done(struct crypto_async_request *base, int err)
 #endif
        }
 
-       err = ah->nexthdr;
-
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_output_resume(skb, err);
 }
@@ -466,12 +464,12 @@ static void ah6_input_done(struct crypto_async_request *base, int err)
        if (err)
                goto out;
 
+       err = ah->nexthdr;
+
        skb->network_header += ah_hlen;
        memcpy(skb_network_header(skb), work_iph, hdr_len);
        __skb_pull(skb, ah_hlen + hdr_len);
        skb_set_transport_header(skb, -hdr_len);
-
-       err = ah->nexthdr;
 out:
        kfree(AH_SKB_CB(skb)->tmp);
        xfrm_input_resume(skb, err);
@@ -583,8 +581,6 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb)
                if (err == -EINPROGRESS)
                        goto out;
 
-               if (err == -EBUSY)
-                       err = NET_XMIT_DROP;
                goto out_free;
        }
 
index fee46d5..1567fb1 100644 (file)
@@ -85,7 +85,7 @@ struct dst_entry *inet6_csk_route_req(struct sock *sk,
  * request_sock (formerly open request) hash tables.
  */
 static u32 inet6_synq_hash(const struct in6_addr *raddr, const __be16 rport,
-                          const u32 rnd, const u16 synq_hsize)
+                          const u32 rnd, const u32 synq_hsize)
 {
        u32 c;
 
index 027c7ff..a46c64e 100644 (file)
@@ -111,6 +111,14 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
            ipv6_addr_loopback(&hdr->daddr))
                goto err;
 
+       /*
+        * RFC4291 2.7
+        * Multicast addresses must not be used as source addresses in IPv6
+        * packets or appear in any Routing header.
+        */
+       if (ipv6_addr_is_multicast(&hdr->saddr))
+               goto err;
+
        skb->transport_header = skb->network_header + sizeof(*hdr);
        IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
 
index bdc15c9..4e2e9ff 100644 (file)
@@ -289,6 +289,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p)
        if ((err = register_netdevice(dev)) < 0)
                goto failed_free;
 
+       strcpy(t->parms.name, dev->name);
+
        dev_hold(dev);
        ip6_tnl_link(ip6n, t);
        return t;
@@ -1407,7 +1409,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev)
        struct ip6_tnl *t = netdev_priv(dev);
 
        t->dev = dev;
-       strcpy(t->parms.name, dev->name);
        dev->tstats = alloc_percpu(struct pcpu_tstats);
        if (!dev->tstats)
                return -ENOMEM;
@@ -1487,6 +1488,7 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n)
 static int __net_init ip6_tnl_init_net(struct net *net)
 {
        struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id);
+       struct ip6_tnl *t = NULL;
        int err;
 
        ip6n->tnls[0] = ip6n->tnls_wc;
@@ -1507,6 +1509,10 @@ static int __net_init ip6_tnl_init_net(struct net *net)
        err = register_netdev(ip6n->fb_tnl_dev);
        if (err < 0)
                goto err_register;
+
+       t = netdev_priv(ip6n->fb_tnl_dev);
+
+       strcpy(t->parms.name, ip6n->fb_tnl_dev->name);
        return 0;
 
 err_register:
index c99e3ee..26cb08c 100644 (file)
@@ -503,7 +503,7 @@ done:
                        goto e_inval;
                if (val > 255 || val < -1)
                        goto e_inval;
-               np->mcast_hops = val;
+               np->mcast_hops = (val == -1 ? IPV6_DEFAULT_MCASTHOPS : val);
                retv = 0;
                break;
 
index 44e5b7f..0cb78d7 100644 (file)
@@ -1571,7 +1571,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
        }
        if (!rt->rt6i_peer)
                rt6_bind_peer(rt, 1);
-       if (inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
+       if (!inet_peer_xrlim_allow(rt->rt6i_peer, 1*HZ))
                goto release;
 
        if (dev->addr_len) {
index 4484648..f792b34 100644 (file)
@@ -186,7 +186,6 @@ config IP6_NF_MANGLE
 
 config IP6_NF_RAW
        tristate  'raw table support (required for TRACE)'
-       depends on NETFILTER_ADVANCED
        help
          This option adds a `raw' table to ip6tables. This table is the very
          first in the netfilter framework and hooks in at the PREROUTING
index 8473016..3399dd3 100644 (file)
@@ -77,7 +77,7 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort,
                                    const struct in6_addr *dest);
 static struct dst_entry        *ip6_dst_check(struct dst_entry *dst, u32 cookie);
 static unsigned int     ip6_default_advmss(const struct dst_entry *dst);
-static unsigned int     ip6_default_mtu(const struct dst_entry *dst);
+static unsigned int     ip6_mtu(const struct dst_entry *dst);
 static struct dst_entry *ip6_negative_advice(struct dst_entry *);
 static void            ip6_dst_destroy(struct dst_entry *);
 static void            ip6_dst_ifdown(struct dst_entry *,
@@ -144,7 +144,7 @@ static struct dst_ops ip6_dst_ops_template = {
        .gc_thresh              =       1024,
        .check                  =       ip6_dst_check,
        .default_advmss         =       ip6_default_advmss,
-       .default_mtu            =       ip6_default_mtu,
+       .mtu                    =       ip6_mtu,
        .cow_metrics            =       ipv6_cow_metrics,
        .destroy                =       ip6_dst_destroy,
        .ifdown                 =       ip6_dst_ifdown,
@@ -155,9 +155,11 @@ static struct dst_ops ip6_dst_ops_template = {
        .neigh_lookup           =       ip6_neigh_lookup,
 };
 
-static unsigned int ip6_blackhole_default_mtu(const struct dst_entry *dst)
+static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst)
 {
-       return 0;
+       unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
+
+       return mtu ? : dst->dev->mtu;
 }
 
 static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
@@ -175,7 +177,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
        .protocol               =       cpu_to_be16(ETH_P_IPV6),
        .destroy                =       ip6_dst_destroy,
        .check                  =       ip6_dst_check,
-       .default_mtu            =       ip6_blackhole_default_mtu,
+       .mtu                    =       ip6_blackhole_mtu,
        .default_advmss         =       ip6_default_advmss,
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
        .cow_metrics            =       ip6_rt_blackhole_cow_metrics,
@@ -1041,10 +1043,15 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
        return mtu;
 }
 
-static unsigned int ip6_default_mtu(const struct dst_entry *dst)
+static unsigned int ip6_mtu(const struct dst_entry *dst)
 {
-       unsigned int mtu = IPV6_MIN_MTU;
        struct inet6_dev *idev;
+       unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
+
+       if (mtu)
+               return mtu;
+
+       mtu = IPV6_MIN_MTU;
 
        rcu_read_lock();
        idev = __in6_dev_get(dst->dev);
index 36131d1..2dea4bb 100644 (file)
@@ -1255,6 +1255,13 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
        if (!want_cookie || tmp_opt.tstamp_ok)
                TCP_ECN_create_request(req, tcp_hdr(skb));
 
+       treq->iif = sk->sk_bound_dev_if;
+
+       /* So that link locals have meaning */
+       if (!sk->sk_bound_dev_if &&
+           ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
+               treq->iif = inet6_iif(skb);
+
        if (!isn) {
                struct inet_peer *peer = NULL;
 
@@ -1264,12 +1271,6 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
                        atomic_inc(&skb->users);
                        treq->pktopts = skb;
                }
-               treq->iif = sk->sk_bound_dev_if;
-
-               /* So that link locals have meaning */
-               if (!sk->sk_bound_dev_if &&
-                   ipv6_addr_type(&treq->rmt_addr) & IPV6_ADDR_LINKLOCAL)
-                       treq->iif = inet6_iif(skb);
 
                if (want_cookie) {
                        isn = cookie_v6_init_sequence(sk, skb, &req->mss);
index 846f475..8c25419 100644 (file)
@@ -340,7 +340,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct inet_sock *inet = inet_sk(sk);
        struct sk_buff *skb;
-       unsigned int ulen;
+       unsigned int ulen, copied;
        int peeked;
        int err;
        int is_udplite = IS_UDPLITE(sk);
@@ -363,9 +363,10 @@ try_again:
                goto out;
 
        ulen = skb->len - sizeof(struct udphdr);
-       if (len > ulen)
-               len = ulen;
-       else if (len < ulen)
+       copied = len;
+       if (copied > ulen)
+               copied = ulen;
+       else if (copied < ulen)
                msg->msg_flags |= MSG_TRUNC;
 
        is_udp4 = (skb->protocol == htons(ETH_P_IP));
@@ -376,14 +377,14 @@ try_again:
         * coverage checksum (UDP-Lite), do it before the copy.
         */
 
-       if (len < ulen || UDP_SKB_CB(skb)->partial_cov) {
+       if (copied < ulen || UDP_SKB_CB(skb)->partial_cov) {
                if (udp_lib_checksum_complete(skb))
                        goto csum_copy_err;
        }
 
        if (skb_csum_unnecessary(skb))
                err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr),
-                                             msg->msg_iov,len);
+                                             msg->msg_iov, copied       );
        else {
                err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
                if (err == -EINVAL)
@@ -432,7 +433,7 @@ try_again:
                        datagram_recv_ctl(sk, msg, skb);
        }
 
-       err = len;
+       err = copied;
        if (flags & MSG_TRUNC)
                err = ulen;
 
index bf8d50c..89ff8c6 100644 (file)
@@ -756,9 +756,6 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
                goto error;
        }
 
-       /* Point to L2TP header */
-       optr = ptr = skb->data;
-
        /* Trace packet contents, if enabled */
        if (tunnel->debug & L2TP_MSG_DATA) {
                length = min(32u, skb->len);
@@ -769,12 +766,15 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
 
                offset = 0;
                do {
-                       printk(" %02X", ptr[offset]);
+                       printk(" %02X", skb->data[offset]);
                } while (++offset < length);
 
                printk("\n");
        }
 
+       /* Point to L2TP header */
+       optr = ptr = skb->data;
+
        /* Get L2TP header flags */
        hdrflags = ntohs(*(__be16 *) ptr);
 
@@ -1072,7 +1072,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len
 
        /* Get routing info from the tunnel socket */
        skb_dst_drop(skb);
-       skb_dst_set(skb, dst_clone(__sk_dst_get(sk)));
+       skb_dst_set(skb, dst_clone(__sk_dst_check(sk, 0)));
 
        inet = inet_sk(sk);
        fl = &inet->cork.fl;
index b3f6552..b064e4d 100644 (file)
@@ -161,6 +161,12 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                return -ENOENT;
        }
 
+       /* if we're already stopping ignore any new requests to stop */
+       if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
+               spin_unlock_bh(&sta->lock);
+               return -EALREADY;
+       }
+
        if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
                /* not even started yet! */
                ieee80211_assign_tid_tx(sta, tid, NULL);
@@ -169,6 +175,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
                return 0;
        }
 
+       set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
+
        spin_unlock_bh(&sta->lock);
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
@@ -176,8 +184,6 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
               sta->sta.addr, tid);
 #endif /* CONFIG_MAC80211_HT_DEBUG */
 
-       set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
-
        del_timer_sync(&tid_tx->addba_resp_timer);
 
        /*
@@ -187,6 +193,20 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
         */
        clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
 
+       /*
+        * There might be a few packets being processed right now (on
+        * another CPU) that have already gotten past the aggregation
+        * check when it was still OPERATIONAL and consequently have
+        * IEEE80211_TX_CTL_AMPDU set. In that case, this code might
+        * call into the driver at the same time or even before the
+        * TX paths calls into it, which could confuse the driver.
+        *
+        * Wait for all currently running TX paths to finish before
+        * telling the driver. New packets will not go through since
+        * the aggregation session is no longer OPERATIONAL.
+        */
+       synchronize_net();
+
        tid_tx->stop_initiator = initiator;
        tid_tx->tx_stop = tx;
 
@@ -757,11 +777,27 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
                goto out;
        }
 
-       del_timer(&tid_tx->addba_resp_timer);
+       del_timer_sync(&tid_tx->addba_resp_timer);
 
 #ifdef CONFIG_MAC80211_HT_DEBUG
        printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid);
 #endif
+
+       /*
+        * addba_resp_timer may have fired before we got here, and
+        * caused WANT_STOP to be set. If the stop then was already
+        * processed further, STOPPING might be set.
+        */
+       if (test_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state) ||
+           test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
+#ifdef CONFIG_MAC80211_HT_DEBUG
+               printk(KERN_DEBUG
+                      "got addBA resp for tid %d but we already gave up\n",
+                      tid);
+#endif
+               goto out;
+       }
+
        /*
         * IEEE 802.11-2007 7.3.1.14:
         * In an ADDBA Response frame, when the Status Code field
index c5f3417..3110cbd 100644 (file)
@@ -274,9 +274,9 @@ static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf,
 
                PRINT_HT_CAP((htc->cap & BIT(10)), "HT Delayed Block Ack");
 
-               PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: "
-                            "3839 bytes");
                PRINT_HT_CAP(!(htc->cap & BIT(11)), "Max AMSDU length: "
+                            "3839 bytes");
+               PRINT_HT_CAP((htc->cap & BIT(11)), "Max AMSDU length: "
                             "7935 bytes");
 
                /*
index 72c8bea..b1b1bb3 100644 (file)
@@ -1487,6 +1487,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
        int i, j, err;
        bool have_higher_than_11mbit = false;
        u16 ap_ht_cap_flags;
+       int min_rate = INT_MAX, min_rate_index = -1;
 
        /* AssocResp and ReassocResp have identical structure */
 
@@ -1553,6 +1554,10 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
                                rates |= BIT(j);
                                if (is_basic)
                                        basic_rates |= BIT(j);
+                               if (rate < min_rate) {
+                                       min_rate = rate;
+                                       min_rate_index = j;
+                               }
                                break;
                        }
                }
@@ -1570,11 +1575,25 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
                                rates |= BIT(j);
                                if (is_basic)
                                        basic_rates |= BIT(j);
+                               if (rate < min_rate) {
+                                       min_rate = rate;
+                                       min_rate_index = j;
+                               }
                                break;
                        }
                }
        }
 
+       /*
+        * some buggy APs don't advertise basic_rates. use the lowest
+        * supported rate instead.
+        */
+       if (unlikely(!basic_rates) && min_rate_index >= 0) {
+               printk(KERN_DEBUG "%s: No basic rates in AssocResp. "
+                      "Using min supported rate instead.\n", sdata->name);
+               basic_rates = BIT(min_rate_index);
+       }
+
        sta->sta.supp_rates[wk->chan->band] = rates;
        sdata->vif.bss_conf.basic_rates = basic_rates;
 
@@ -2269,6 +2288,7 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
 
        cancel_work_sync(&ifmgd->request_smps_work);
 
+       cancel_work_sync(&ifmgd->monitor_work);
        cancel_work_sync(&ifmgd->beacon_connection_loss_work);
        if (del_timer_sync(&ifmgd->timer))
                set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@@ -2277,7 +2297,6 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
        if (del_timer_sync(&ifmgd->chswitch_timer))
                set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
 
-       cancel_work_sync(&ifmgd->monitor_work);
        /* these will just be re-established on connection */
        del_timer_sync(&ifmgd->conn_mon_timer);
        del_timer_sync(&ifmgd->bcn_mon_timer);
index bb53726..fb123e2 100644 (file)
@@ -141,8 +141,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        pos++;
 
        /* IEEE80211_RADIOTAP_RATE */
-       if (status->flag & RX_FLAG_HT) {
+       if (!rate || status->flag & RX_FLAG_HT) {
                /*
+                * Without rate information don't add it. If we have,
                 * MCS information is a separate field in radiotap,
                 * added below. The byte here is needed as padding
                 * for the channel though, so initialise it to 0.
@@ -163,12 +164,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        else if (status->flag & RX_FLAG_HT)
                put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
                                   pos);
-       else if (rate->flags & IEEE80211_RATE_ERP_G)
+       else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
                put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
                                   pos);
-       else
+       else if (rate)
                put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
                                   pos);
+       else
+               put_unaligned_le16(IEEE80211_CHAN_2GHZ, pos);
        pos += 2;
 
        /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
index ce962d2..8eaa746 100644 (file)
@@ -1354,12 +1354,12 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
                         * Use MoreData flag to indicate whether there are
                         * more buffered frames for this STA
                         */
-                       if (!more_data)
-                               hdr->frame_control &=
-                                       cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
-                       else
+                       if (more_data || !skb_queue_empty(&frames))
                                hdr->frame_control |=
                                        cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+                       else
+                               hdr->frame_control &=
+                                       cpu_to_le16(~IEEE80211_FCTL_MOREDATA);
 
                        if (ieee80211_is_data_qos(hdr->frame_control) ||
                            ieee80211_is_qos_nullfunc(hdr->frame_control))
index 80de436..16518f3 100644 (file)
@@ -260,7 +260,7 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct ieee80211_radiotap_header *rthdr;
        unsigned char *pos;
-       __le16 txflags;
+       u16 txflags;
 
        rthdr = (struct ieee80211_radiotap_header *) skb_push(skb, rtap_len);
 
@@ -290,13 +290,13 @@ static void ieee80211_add_tx_radiotap_header(struct ieee80211_supported_band
        txflags = 0;
        if (!(info->flags & IEEE80211_TX_STAT_ACK) &&
            !is_multicast_ether_addr(hdr->addr1))
-               txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL);
+               txflags |= IEEE80211_RADIOTAP_F_TX_FAIL;
 
        if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
            (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
-               txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS);
+               txflags |= IEEE80211_RADIOTAP_F_TX_CTS;
        else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
-               txflags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS);
+               txflags |= IEEE80211_RADIOTAP_F_TX_RTS;
 
        put_unaligned_le16(txflags, pos);
        pos += 2;
index 51e256c..eca0fad 100644 (file)
@@ -881,6 +881,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
        skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
                                     ssid, ssid_len,
                                     buf, buf_len);
+       if (!skb)
+               goto out;
 
        if (dst) {
                mgmt = (struct ieee80211_mgmt *) skb->data;
@@ -889,6 +891,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
        }
 
        IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+
+ out:
        kfree(buf);
 
        return skb;
index 8260b13..d5597b7 100644 (file)
@@ -201,7 +201,6 @@ config NF_CONNTRACK_BROADCAST
 
 config NF_CONNTRACK_NETBIOS_NS
        tristate "NetBIOS name service protocol support"
-       depends on NETFILTER_ADVANCED
        select NF_CONNTRACK_BROADCAST
        help
          NetBIOS name service requests are sent as broadcast messages from an
@@ -542,7 +541,6 @@ config NETFILTER_XT_TARGET_NOTRACK
        tristate  '"NOTRACK" target support'
        depends on IP_NF_RAW || IP6_NF_RAW
        depends on NF_CONNTRACK
-       depends on NETFILTER_ADVANCED
        help
          The NOTRACK target allows a select rule to specify
          which packets *not* to enter the conntrack/NAT
index 6ee10f5..37d667e 100644 (file)
@@ -158,7 +158,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipport4_elem data = { };
-       u32 ip, ip_to, p = 0, port, port_to;
+       u32 ip, ip_to = 0, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
index fb90e34..e69e271 100644 (file)
@@ -162,7 +162,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportip4_elem data = { };
-       u32 ip, ip_to, p = 0, port, port_to;
+       u32 ip, ip_to = 0, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
index deb3e3d..64199b4 100644 (file)
@@ -184,7 +184,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
-       u32 ip, ip_to, p = 0, port, port_to;
+       u32 ip, ip_to = 0, p = 0, port, port_to;
        u32 ip2_from = 0, ip2_to, ip2_last, ip2;
        u32 timeout = h->timeout;
        bool with_ports = false;
index 6b368be..b62c414 100644 (file)
 
 static DEFINE_MUTEX(nf_ct_ecache_mutex);
 
-struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb __read_mostly;
-EXPORT_SYMBOL_GPL(nf_conntrack_event_cb);
-
-struct nf_exp_event_notifier __rcu *nf_expect_event_cb __read_mostly;
-EXPORT_SYMBOL_GPL(nf_expect_event_cb);
-
 /* deliver cached events and clear cache entry - must be called with locally
  * disabled softirqs */
 void nf_ct_deliver_cached_events(struct nf_conn *ct)
 {
+       struct net *net = nf_ct_net(ct);
        unsigned long events;
        struct nf_ct_event_notifier *notify;
        struct nf_conntrack_ecache *e;
 
        rcu_read_lock();
-       notify = rcu_dereference(nf_conntrack_event_cb);
+       notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
        if (notify == NULL)
                goto out_unlock;
 
@@ -83,19 +78,20 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(nf_ct_deliver_cached_events);
 
-int nf_conntrack_register_notifier(struct nf_ct_event_notifier *new)
+int nf_conntrack_register_notifier(struct net *net,
+                                  struct nf_ct_event_notifier *new)
 {
        int ret = 0;
        struct nf_ct_event_notifier *notify;
 
        mutex_lock(&nf_ct_ecache_mutex);
-       notify = rcu_dereference_protected(nf_conntrack_event_cb,
+       notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb,
                                           lockdep_is_held(&nf_ct_ecache_mutex));
        if (notify != NULL) {
                ret = -EBUSY;
                goto out_unlock;
        }
-       RCU_INIT_POINTER(nf_conntrack_event_cb, new);
+       RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, new);
        mutex_unlock(&nf_ct_ecache_mutex);
        return ret;
 
@@ -105,32 +101,34 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_register_notifier);
 
-void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *new)
+void nf_conntrack_unregister_notifier(struct net *net,
+                                     struct nf_ct_event_notifier *new)
 {
        struct nf_ct_event_notifier *notify;
 
        mutex_lock(&nf_ct_ecache_mutex);
-       notify = rcu_dereference_protected(nf_conntrack_event_cb,
+       notify = rcu_dereference_protected(net->ct.nf_conntrack_event_cb,
                                           lockdep_is_held(&nf_ct_ecache_mutex));
        BUG_ON(notify != new);
-       RCU_INIT_POINTER(nf_conntrack_event_cb, NULL);
+       RCU_INIT_POINTER(net->ct.nf_conntrack_event_cb, NULL);
        mutex_unlock(&nf_ct_ecache_mutex);
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_unregister_notifier);
 
-int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *new)
+int nf_ct_expect_register_notifier(struct net *net,
+                                  struct nf_exp_event_notifier *new)
 {
        int ret = 0;
        struct nf_exp_event_notifier *notify;
 
        mutex_lock(&nf_ct_ecache_mutex);
-       notify = rcu_dereference_protected(nf_expect_event_cb,
+       notify = rcu_dereference_protected(net->ct.nf_expect_event_cb,
                                           lockdep_is_held(&nf_ct_ecache_mutex));
        if (notify != NULL) {
                ret = -EBUSY;
                goto out_unlock;
        }
-       RCU_INIT_POINTER(nf_expect_event_cb, new);
+       RCU_INIT_POINTER(net->ct.nf_expect_event_cb, new);
        mutex_unlock(&nf_ct_ecache_mutex);
        return ret;
 
@@ -140,15 +138,16 @@ out_unlock:
 }
 EXPORT_SYMBOL_GPL(nf_ct_expect_register_notifier);
 
-void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *new)
+void nf_ct_expect_unregister_notifier(struct net *net,
+                                     struct nf_exp_event_notifier *new)
 {
        struct nf_exp_event_notifier *notify;
 
        mutex_lock(&nf_ct_ecache_mutex);
-       notify = rcu_dereference_protected(nf_expect_event_cb,
+       notify = rcu_dereference_protected(net->ct.nf_expect_event_cb,
                                           lockdep_is_held(&nf_ct_ecache_mutex));
        BUG_ON(notify != new);
-       RCU_INIT_POINTER(nf_expect_event_cb, NULL);
+       RCU_INIT_POINTER(net->ct.nf_expect_event_cb, NULL);
        mutex_unlock(&nf_ct_ecache_mutex);
 }
 EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
index e58aa9b..ef21b22 100644 (file)
@@ -4,7 +4,7 @@
  * (C) 2001 by Jay Schulist <jschlst@samba.org>
  * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
  * (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005-2008 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org>
  *
  * Initial connection tracking via netlink development funded and
  * generally made possible by Network Robots, Inc. (www.networkrobots.com)
@@ -2163,6 +2163,54 @@ MODULE_ALIAS("ip_conntrack_netlink");
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK);
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_EXP);
 
+static int __net_init ctnetlink_net_init(struct net *net)
+{
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+       int ret;
+
+       ret = nf_conntrack_register_notifier(net, &ctnl_notifier);
+       if (ret < 0) {
+               pr_err("ctnetlink_init: cannot register notifier.\n");
+               goto err_out;
+       }
+
+       ret = nf_ct_expect_register_notifier(net, &ctnl_notifier_exp);
+       if (ret < 0) {
+               pr_err("ctnetlink_init: cannot expect register notifier.\n");
+               goto err_unreg_notifier;
+       }
+#endif
+       return 0;
+
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+err_unreg_notifier:
+       nf_conntrack_unregister_notifier(net, &ctnl_notifier);
+err_out:
+       return ret;
+#endif
+}
+
+static void ctnetlink_net_exit(struct net *net)
+{
+#ifdef CONFIG_NF_CONNTRACK_EVENTS
+       nf_ct_expect_unregister_notifier(net, &ctnl_notifier_exp);
+       nf_conntrack_unregister_notifier(net, &ctnl_notifier);
+#endif
+}
+
+static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list)
+{
+       struct net *net;
+
+       list_for_each_entry(net, net_exit_list, exit_list)
+               ctnetlink_net_exit(net);
+}
+
+static struct pernet_operations ctnetlink_net_ops = {
+       .init           = ctnetlink_net_init,
+       .exit_batch     = ctnetlink_net_exit_batch,
+};
+
 static int __init ctnetlink_init(void)
 {
        int ret;
@@ -2180,28 +2228,15 @@ static int __init ctnetlink_init(void)
                goto err_unreg_subsys;
        }
 
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
-       ret = nf_conntrack_register_notifier(&ctnl_notifier);
-       if (ret < 0) {
-               pr_err("ctnetlink_init: cannot register notifier.\n");
+       if (register_pernet_subsys(&ctnetlink_net_ops)) {
+               pr_err("ctnetlink_init: cannot register pernet operations\n");
                goto err_unreg_exp_subsys;
        }
 
-       ret = nf_ct_expect_register_notifier(&ctnl_notifier_exp);
-       if (ret < 0) {
-               pr_err("ctnetlink_init: cannot expect register notifier.\n");
-               goto err_unreg_notifier;
-       }
-#endif
-
        return 0;
 
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
-err_unreg_notifier:
-       nf_conntrack_unregister_notifier(&ctnl_notifier);
 err_unreg_exp_subsys:
        nfnetlink_subsys_unregister(&ctnl_exp_subsys);
-#endif
 err_unreg_subsys:
        nfnetlink_subsys_unregister(&ctnl_subsys);
 err_out:
@@ -2213,11 +2248,7 @@ static void __exit ctnetlink_exit(void)
        pr_info("ctnetlink: unregistering from nfnetlink.\n");
 
        nf_ct_remove_userspace_expectations();
-#ifdef CONFIG_NF_CONNTRACK_EVENTS
-       nf_ct_expect_unregister_notifier(&ctnl_notifier_exp);
-       nf_conntrack_unregister_notifier(&ctnl_notifier);
-#endif
-
+       unregister_pernet_subsys(&ctnetlink_net_ops);
        nfnetlink_subsys_unregister(&ctnl_exp_subsys);
        nfnetlink_subsys_unregister(&ctnl_subsys);
 }
index 9c24de1..824f184 100644 (file)
@@ -111,8 +111,6 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
        struct netlbl_domaddr_map *addrmap = NULL;
        struct netlbl_domaddr4_map *map4 = NULL;
        struct netlbl_domaddr6_map *map6 = NULL;
-       const struct in_addr *addr4, *mask4;
-       const struct in6_addr *addr6, *mask6;
 
        entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (entry == NULL)
@@ -133,9 +131,9 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
                INIT_LIST_HEAD(&addrmap->list6);
 
                switch (family) {
-               case AF_INET:
-                       addr4 = addr;
-                       mask4 = mask;
+               case AF_INET: {
+                       const struct in_addr *addr4 = addr;
+                       const struct in_addr *mask4 = mask;
                        map4 = kzalloc(sizeof(*map4), GFP_ATOMIC);
                        if (map4 == NULL)
                                goto cfg_unlbl_map_add_failure;
@@ -148,9 +146,11 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
                        if (ret_val != 0)
                                goto cfg_unlbl_map_add_failure;
                        break;
-               case AF_INET6:
-                       addr6 = addr;
-                       mask6 = mask;
+                       }
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               case AF_INET6: {
+                       const struct in6_addr *addr6 = addr;
+                       const struct in6_addr *mask6 = mask;
                        map6 = kzalloc(sizeof(*map6), GFP_ATOMIC);
                        if (map6 == NULL)
                                goto cfg_unlbl_map_add_failure;
@@ -162,11 +162,13 @@ int netlbl_cfg_unlbl_map_add(const char *domain,
                        map6->list.addr.s6_addr32[3] &= mask6->s6_addr32[3];
                        ipv6_addr_copy(&map6->list.mask, mask6);
                        map6->list.valid = 1;
-                       ret_val = netlbl_af4list_add(&map4->list,
-                                                    &addrmap->list4);
+                       ret_val = netlbl_af6list_add(&map6->list,
+                                                    &addrmap->list6);
                        if (ret_val != 0)
                                goto cfg_unlbl_map_add_failure;
                        break;
+                       }
+#endif /* IPv6 */
                default:
                        goto cfg_unlbl_map_add_failure;
                        break;
@@ -225,9 +227,11 @@ int netlbl_cfg_unlbl_static_add(struct net *net,
        case AF_INET:
                addr_len = sizeof(struct in_addr);
                break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        case AF_INET6:
                addr_len = sizeof(struct in6_addr);
                break;
+#endif /* IPv6 */
        default:
                return -EPFNOSUPPORT;
        }
@@ -266,9 +270,11 @@ int netlbl_cfg_unlbl_static_del(struct net *net,
        case AF_INET:
                addr_len = sizeof(struct in_addr);
                break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
        case AF_INET6:
                addr_len = sizeof(struct in6_addr);
                break;
+#endif /* IPv6 */
        default:
                return -EPFNOSUPPORT;
        }
index 4cf6dc7..ec753b3 100644 (file)
@@ -9,7 +9,6 @@ config RDS
 
 config RDS_RDMA
        tristate "RDS over Infiniband and iWARP"
-       select LLIST
        depends on RDS && INFINIBAND && INFINIBAND_ADDR_TRANS
        ---help---
          Allow RDS to use Infiniband and iWARP as a transport.
index 6649463..d617161 100644 (file)
@@ -209,8 +209,8 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt)
                                 ctl->Plog, ctl->Scell_log,
                                 nla_data(tb[TCA_RED_STAB]));
 
-       if (skb_queue_empty(&sch->q))
-               red_end_of_idle_period(&q->parms);
+       if (!q->qdisc->q.qlen)
+               red_start_of_idle_period(&q->parms);
 
        sch_tree_unlock(sch);
        return 0;
index a3b7120..4f4c52c 100644 (file)
@@ -225,11 +225,11 @@ static int teql_qdisc_init(struct Qdisc *sch, struct nlattr *opt)
 
 
 static int
-__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *dev)
+__teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res,
+              struct net_device *dev, struct netdev_queue *txq,
+              struct neighbour *mn)
 {
-       struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, 0);
-       struct teql_sched_data *q = qdisc_priv(dev_queue->qdisc);
-       struct neighbour *mn = dst_get_neighbour(skb_dst(skb));
+       struct teql_sched_data *q = qdisc_priv(txq->qdisc);
        struct neighbour *n = q->ncache;
 
        if (mn->tbl == NULL)
@@ -262,17 +262,26 @@ __teql_resolve(struct sk_buff *skb, struct sk_buff *skb_res, struct net_device *
 }
 
 static inline int teql_resolve(struct sk_buff *skb,
-                              struct sk_buff *skb_res, struct net_device *dev)
+                              struct sk_buff *skb_res,
+                              struct net_device *dev,
+                              struct netdev_queue *txq)
 {
-       struct netdev_queue *txq = netdev_get_tx_queue(dev, 0);
+       struct dst_entry *dst = skb_dst(skb);
+       struct neighbour *mn;
+       int res;
+
        if (txq->qdisc == &noop_qdisc)
                return -ENODEV;
 
-       if (dev->header_ops == NULL ||
-           skb_dst(skb) == NULL ||
-           dst_get_neighbour(skb_dst(skb)) == NULL)
+       if (!dev->header_ops || !dst)
                return 0;
-       return __teql_resolve(skb, skb_res, dev);
+
+       rcu_read_lock();
+       mn = dst_get_neighbour(dst);
+       res = mn ? __teql_resolve(skb, skb_res, dev, txq, mn) : 0;
+       rcu_read_unlock();
+
+       return res;
 }
 
 static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -307,7 +316,7 @@ restart:
                        continue;
                }
 
-               switch (teql_resolve(skb, skb_res, slave)) {
+               switch (teql_resolve(skb, skb_res, slave, slave_txq)) {
                case 0:
                        if (__netif_tx_trylock(slave_txq)) {
                                unsigned int length = qdisc_pkt_len(skb);
index 865e68f..bf81204 100644 (file)
@@ -82,7 +82,7 @@ static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp)
        struct sctp_auth_bytes *key;
 
        /* Verify that we are not going to overflow INT_MAX */
-       if ((INT_MAX - key_len) < sizeof(struct sctp_auth_bytes))
+       if (key_len > (INT_MAX - sizeof(struct sctp_auth_bytes)))
                return NULL;
 
        /* Allocate the shared key */
index d7f97ef..55472c4 100644 (file)
@@ -496,7 +496,7 @@ static int xs_nospace(struct rpc_task *task)
        struct rpc_rqst *req = task->tk_rqstp;
        struct rpc_xprt *xprt = req->rq_xprt;
        struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
-       int ret = 0;
+       int ret = -EAGAIN;
 
        dprintk("RPC: %5u xmit incomplete (%u left of %u)\n",
                        task->tk_pid, req->rq_slen - req->rq_bytes_sent,
@@ -508,7 +508,6 @@ static int xs_nospace(struct rpc_task *task)
        /* Don't race with disconnect */
        if (xprt_connected(xprt)) {
                if (test_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags)) {
-                       ret = -EAGAIN;
                        /*
                         * Notify TCP that we're limited by the application
                         * window size
@@ -2530,8 +2529,10 @@ static struct rpc_xprt *xs_setup_xprt(struct xprt_create *args,
                int err;
                err = xs_init_anyaddr(args->dstaddr->sa_family,
                                        (struct sockaddr *)&new->srcaddr);
-               if (err != 0)
+               if (err != 0) {
+                       xprt_free(xprt);
                        return ERR_PTR(err);
+               }
        }
 
        return xprt;
index 466fbcc..b595a3d 100644 (file)
@@ -1957,6 +1957,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                        if ((UNIXCB(skb).pid  != siocb->scm->pid) ||
                            (UNIXCB(skb).cred != siocb->scm->cred)) {
                                skb_queue_head(&sk->sk_receive_queue, skb);
+                               sk->sk_data_ready(sk, skb->len);
                                break;
                        }
                } else {
@@ -1974,6 +1975,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                chunk = min_t(unsigned int, skb->len, size);
                if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
                        skb_queue_head(&sk->sk_receive_queue, skb);
+                       sk->sk_data_ready(sk, skb->len);
                        if (copied == 0)
                                copied = -EFAULT;
                        break;
@@ -1991,6 +1993,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
                        /* put the skb back if we didn't use it up.. */
                        if (skb->len) {
                                skb_queue_head(&sk->sk_receive_queue, skb);
+                               sk->sk_data_ready(sk, skb->len);
                                break;
                        }
 
@@ -2006,6 +2009,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 
                        /* put message back and return */
                        skb_queue_head(&sk->sk_receive_queue, skb);
+                       sk->sk_data_ready(sk, skb->len);
                        break;
                }
        } while (size);
index 48260c2..ffafda5 100644 (file)
@@ -89,8 +89,8 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 },
        [NL80211_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
 
-       [NL80211_ATTR_MAC] = { .type = NLA_BINARY, .len = ETH_ALEN },
-       [NL80211_ATTR_PREV_BSSID] = { .type = NLA_BINARY, .len = ETH_ALEN },
+       [NL80211_ATTR_MAC] = { .len = ETH_ALEN },
+       [NL80211_ATTR_PREV_BSSID] = { .len = ETH_ALEN },
 
        [NL80211_ATTR_KEY] = { .type = NLA_NESTED, },
        [NL80211_ATTR_KEY_DATA] = { .type = NLA_BINARY,
@@ -132,8 +132,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
        [NL80211_ATTR_MESH_CONFIG] = { .type = NLA_NESTED },
        [NL80211_ATTR_SUPPORT_MESH_AUTH] = { .type = NLA_FLAG },
 
-       [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY,
-                                        .len = NL80211_HT_CAPABILITY_LEN },
+       [NL80211_ATTR_HT_CAPABILITY] = { .len = NL80211_HT_CAPABILITY_LEN },
 
        [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 },
        [NL80211_ATTR_IE] = { .type = NLA_BINARY,
@@ -1253,6 +1252,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                        goto bad_res;
                }
 
+               if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
+                   netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
+                       result = -EINVAL;
+                       goto bad_res;
+               }
+
                nla_for_each_nested(nl_txq_params,
                                    info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
                                    rem_txq_params) {
index 6acba9d..77e9267 100644 (file)
@@ -2037,6 +2037,10 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
        }
 
        request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
+       if (!request_wiphy) {
+               reg_set_request_processed();
+               return -ENODEV;
+       }
 
        if (!last_request->intersect) {
                int r;
@@ -2265,6 +2269,9 @@ void /* __init_or_exit */ regulatory_exit(void)
 
        kfree(last_request);
 
+       last_request = NULL;
+       dev_set_uevent_suppress(&reg_pdev->dev, true);
+
        platform_device_unregister(reg_pdev);
 
        spin_lock_bh(&reg_pending_beacons_lock);
index 0fb1424..dc23b31 100644 (file)
@@ -259,17 +259,20 @@ static int cmp_ies(u8 num, u8 *ies1, size_t len1, u8 *ies2, size_t len2)
 {
        const u8 *ie1 = cfg80211_find_ie(num, ies1, len1);
        const u8 *ie2 = cfg80211_find_ie(num, ies2, len2);
-       int r;
 
+       /* equal if both missing */
        if (!ie1 && !ie2)
                return 0;
-       if (!ie1 || !ie2)
+       /* sort missing IE before (left of) present IE */
+       if (!ie1)
                return -1;
+       if (!ie2)
+               return 1;
 
-       r = memcmp(ie1 + 2, ie2 + 2, min(ie1[1], ie2[1]));
-       if (r == 0 && ie1[1] != ie2[1])
+       /* sort by length first, then by contents */
+       if (ie1[1] != ie2[1])
                return ie2[1] - ie1[1];
-       return r;
+       return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
 }
 
 static bool is_bss(struct cfg80211_bss *a,
index 552df27..2118d64 100644 (file)
@@ -2382,9 +2382,11 @@ static unsigned int xfrm_default_advmss(const struct dst_entry *dst)
        return dst_metric_advmss(dst->path);
 }
 
-static unsigned int xfrm_default_mtu(const struct dst_entry *dst)
+static unsigned int xfrm_mtu(const struct dst_entry *dst)
 {
-       return dst_mtu(dst->path);
+       unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
+
+       return mtu ? : dst_mtu(dst->path);
 }
 
 static struct neighbour *xfrm_neigh_lookup(const struct dst_entry *dst, const void *daddr)
@@ -2411,8 +2413,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
                        dst_ops->check = xfrm_dst_check;
                if (likely(dst_ops->default_advmss == NULL))
                        dst_ops->default_advmss = xfrm_default_advmss;
-               if (likely(dst_ops->default_mtu == NULL))
-                       dst_ops->default_mtu = xfrm_default_mtu;
+               if (likely(dst_ops->mtu == NULL))
+                       dst_ops->mtu = xfrm_mtu;
                if (likely(dst_ops->negative_advice == NULL))
                        dst_ops->negative_advice = xfrm_negative_advice;
                if (likely(dst_ops->link_failure == NULL))
index 6bc7a86..d6f8433 100644 (file)
@@ -2,5 +2,9 @@
 # Makefile for encrypted keys
 #
 
-obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted.o ecryptfs_format.o
-obj-$(CONFIG_TRUSTED_KEYS) += masterkey_trusted.o
+obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted-keys.o
+
+encrypted-keys-y := encrypted.o ecryptfs_format.o
+masterkey-$(CONFIG_TRUSTED_KEYS) := masterkey_trusted.o
+masterkey-$(CONFIG_TRUSTED_KEYS)-$(CONFIG_ENCRYPTED_KEYS) := masterkey_trusted.o
+encrypted-keys-y += $(masterkey-y) $(masterkey-m-m)
index dcc843c..41144f7 100644 (file)
@@ -444,7 +444,7 @@ static struct key *request_master_key(struct encrypted_key_payload *epayload,
                goto out;
 
        if (IS_ERR(mkey)) {
-               int ret = PTR_ERR(epayload);
+               int ret = PTR_ERR(mkey);
 
                if (ret == -ENOTSUPP)
                        pr_info("encrypted_key: key %s not supported",
index b6ade89..8136a2d 100644 (file)
@@ -2,7 +2,8 @@
 #define __ENCRYPTED_KEY_H
 
 #define ENCRYPTED_DEBUG 0
-#ifdef CONFIG_TRUSTED_KEYS
+#if defined(CONFIG_TRUSTED_KEYS) || \
+  (defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE))
 extern struct key *request_trusted_key(const char *trusted_desc,
                                       u8 **master_key, size_t *master_keylen);
 #else
index 5b366d7..69ff52c 100644 (file)
@@ -102,7 +102,8 @@ int user_update(struct key *key, const void *data, size_t datalen)
                key->expiry = 0;
        }
 
-       kfree_rcu(zap, rcu);
+       if (zap)
+               kfree_rcu(zap, rcu);
 
 error:
        return ret;
index 6aceef5..5c32f36 100644 (file)
@@ -102,9 +102,6 @@ static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
 
 const char *smack_cipso_option = SMACK_CIPSO_OPTION;
 
-
-#define        SEQ_READ_FINISHED       ((loff_t)-1)
-
 /*
  * Values for parsing cipso rules
  * SMK_DIGITLEN: Length of a digit field in a rule.
@@ -357,10 +354,12 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
 
        rc = count;
        /*
+        * If this is "load" as opposed to "load-self" and a new rule
+        * it needs to get added for reporting.
         * smk_set_access returns true if there was already a rule
         * for the subject/object pair, and false if it was new.
         */
-       if (!smk_set_access(rule, rule_list, rule_lock)) {
+       if (load && !smk_set_access(rule, rule_list, rule_lock)) {
                smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
                if (smlp != NULL) {
                        smlp->smk_rule = rule;
@@ -377,12 +376,12 @@ out:
        return rc;
 }
 
-
 /*
- * Seq_file read operations for /smack/load
+ * Core logic for smackfs seq list operations.
  */
 
-static void *load_seq_start(struct seq_file *s, loff_t *pos)
+static void *smk_seq_start(struct seq_file *s, loff_t *pos,
+                               struct list_head *head)
 {
        struct list_head *list;
 
@@ -390,7 +389,7 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
         * This is 0 the first time through.
         */
        if (s->index == 0)
-               s->private = &smack_rule_list;
+               s->private = head;
 
        if (s->private == NULL)
                return NULL;
@@ -404,11 +403,12 @@ static void *load_seq_start(struct seq_file *s, loff_t *pos)
        return list;
 }
 
-static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
+static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
+                               struct list_head *head)
 {
        struct list_head *list = v;
 
-       if (list_is_last(list, &smack_rule_list)) {
+       if (list_is_last(list, head)) {
                s->private = NULL;
                return NULL;
        }
@@ -416,6 +416,25 @@ static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
        return list->next;
 }
 
+static void smk_seq_stop(struct seq_file *s, void *v)
+{
+       /* No-op */
+}
+
+/*
+ * Seq_file read operations for /smack/load
+ */
+
+static void *load_seq_start(struct seq_file *s, loff_t *pos)
+{
+       return smk_seq_start(s, pos, &smack_rule_list);
+}
+
+static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+       return smk_seq_next(s, v, pos, &smack_rule_list);
+}
+
 static int load_seq_show(struct seq_file *s, void *v)
 {
        struct list_head *list = v;
@@ -446,16 +465,11 @@ static int load_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void load_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations load_seq_ops = {
        .start = load_seq_start,
        .next  = load_seq_next,
        .show  = load_seq_show,
-       .stop  = load_seq_stop,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -574,28 +588,12 @@ static void smk_unlbl_ambient(char *oldambient)
 
 static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
 {
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&smack_known_list))
-               return NULL;
-
-       return smack_known_list.next;
+       return smk_seq_start(s, pos, &smack_known_list);
 }
 
 static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct list_head  *list = v;
-
-       /*
-        * labels with no associated cipso value wont be printed
-        * in cipso_seq_show
-        */
-       if (list_is_last(list, &smack_known_list)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-
-       return list->next;
+       return smk_seq_next(s, v, pos, &smack_known_list);
 }
 
 /*
@@ -634,16 +632,11 @@ static int cipso_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void cipso_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations cipso_seq_ops = {
        .start = cipso_seq_start,
-       .stop  = cipso_seq_stop,
        .next  = cipso_seq_next,
        .show  = cipso_seq_show,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -788,23 +781,12 @@ static const struct file_operations smk_cipso_ops = {
 
 static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
 {
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&smk_netlbladdr_list))
-               return NULL;
-       return smk_netlbladdr_list.next;
+       return smk_seq_start(s, pos, &smk_netlbladdr_list);
 }
 
 static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
-       struct list_head *list = v;
-
-       if (list_is_last(list, &smk_netlbladdr_list)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-
-       return list->next;
+       return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
 }
 #define BEBITS (sizeof(__be32) * 8)
 
@@ -828,16 +810,11 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void netlbladdr_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations netlbladdr_seq_ops = {
        .start = netlbladdr_seq_start,
-       .stop  = netlbladdr_seq_stop,
        .next  = netlbladdr_seq_next,
        .show  = netlbladdr_seq_show,
+       .stop  = smk_seq_stop,
 };
 
 /**
@@ -1405,23 +1382,14 @@ static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
 {
        struct task_smack *tsp = current_security();
 
-       if (*pos == SEQ_READ_FINISHED)
-               return NULL;
-       if (list_empty(&tsp->smk_rules))
-               return NULL;
-       return tsp->smk_rules.next;
+       return smk_seq_start(s, pos, &tsp->smk_rules);
 }
 
 static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
        struct task_smack *tsp = current_security();
-       struct list_head *list = v;
 
-       if (list_is_last(list, &tsp->smk_rules)) {
-               *pos = SEQ_READ_FINISHED;
-               return NULL;
-       }
-       return list->next;
+       return smk_seq_next(s, v, pos, &tsp->smk_rules);
 }
 
 static int load_self_seq_show(struct seq_file *s, void *v)
@@ -1453,16 +1421,11 @@ static int load_self_seq_show(struct seq_file *s, void *v)
        return 0;
 }
 
-static void load_self_seq_stop(struct seq_file *s, void *v)
-{
-       /* No-op */
-}
-
 static const struct seq_operations load_self_seq_ops = {
        .start = load_self_seq_start,
        .next  = load_self_seq_next,
        .show  = load_self_seq_show,
-       .stop  = load_self_seq_stop,
+       .stop  = smk_seq_stop,
 };
 
 
index a3ce1b2..1aa52ef 100644 (file)
@@ -876,7 +876,7 @@ static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
                (0x0fUL << 12) |
                (PS3_AUDIO_IOID);
 
-       ret = lv1_gpu_attribute(0x100, 0x007, val, 0, 0);
+       ret = lv1_gpu_attribute(0x100, 0x007, val);
        if (ret)
                pr_info("%s: gpu_attribute failed %d\n", __func__,
                        ret);
index 9c0edad..a4e3237 100644 (file)
@@ -365,7 +365,8 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
        if (ret)
                goto out3;
 
-       mfp_set_groupg(nuc900_audio->dev); /* enbale ac97 multifunction pin*/
+       /* enbale ac97 multifunction pin */
+       mfp_set_groupg(nuc900_audio->dev, "nuc900-audio");
 
        return 0;
 
index 8d02ccb..8b4c253 100755 (executable)
@@ -42,6 +42,7 @@ $default{"BISECT_MANUAL"}     = 0;
 $default{"BISECT_SKIP"}                = 1;
 $default{"SUCCESS_LINE"}       = "login:";
 $default{"DETECT_TRIPLE_FAULT"} = 1;
+$default{"NO_INSTALL"}         = 0;
 $default{"BOOTED_TIMEOUT"}     = 1;
 $default{"DIE_ON_FAILURE"}     = 1;
 $default{"SSH_EXEC"}           = "ssh \$SSH_USER\@\$MACHINE \$SSH_COMMAND";
@@ -84,6 +85,7 @@ my $grub_number;
 my $target;
 my $make;
 my $post_install;
+my $no_install;
 my $noclean;
 my $minconfig;
 my $start_minconfig;
@@ -115,6 +117,7 @@ my $timeout;
 my $booted_timeout;
 my $detect_triplefault;
 my $console;
+my $reboot_success_line;
 my $success_line;
 my $stop_after_success;
 my $stop_after_failure;
@@ -130,6 +133,12 @@ my %config_help;
 my %variable;
 my %force_config;
 
+# do not force reboots on config problems
+my $no_reboot = 1;
+
+# default variables that can be used
+chomp ($variable{"PWD"} = `pwd`);
+
 $config_help{"MACHINE"} = << "EOF"
  The machine hostname that you will test.
 EOF
@@ -241,6 +250,7 @@ sub read_yn {
 
 sub get_ktest_config {
     my ($config) = @_;
+    my $ans;
 
     return if (defined($opt{$config}));
 
@@ -254,16 +264,17 @@ sub get_ktest_config {
        if (defined($default{$config})) {
            print "\[$default{$config}\] ";
        }
-       $entered_configs{$config} = <STDIN>;
-       $entered_configs{$config} =~ s/^\s*(.*\S)\s*$/$1/;
-       if ($entered_configs{$config} =~ /^\s*$/) {
+       $ans = <STDIN>;
+       $ans =~ s/^\s*(.*\S)\s*$/$1/;
+       if ($ans =~ /^\s*$/) {
            if ($default{$config}) {
-               $entered_configs{$config} = $default{$config};
+               $ans = $default{$config};
            } else {
                print "Your answer can not be blank\n";
                next;
            }
        }
+       $entered_configs{$config} = process_variables($ans);
        last;
     }
 }
@@ -298,7 +309,7 @@ sub get_ktest_configs {
 }
 
 sub process_variables {
-    my ($value) = @_;
+    my ($value, $remove_undef) = @_;
     my $retval = "";
 
     # We want to check for '\', and it is just easier
@@ -316,6 +327,10 @@ sub process_variables {
        $retval = "$retval$begin";
        if (defined($variable{$var})) {
            $retval = "$retval$variable{$var}";
+       } elsif (defined($remove_undef) && $remove_undef) {
+           # for if statements, any variable that is not defined,
+           # we simple convert to 0
+           $retval = "${retval}0";
        } else {
            # put back the origin piece.
            $retval = "$retval\$\{$var\}";
@@ -331,10 +346,17 @@ sub process_variables {
 }
 
 sub set_value {
-    my ($lvalue, $rvalue) = @_;
+    my ($lvalue, $rvalue, $override, $overrides, $name) = @_;
 
     if (defined($opt{$lvalue})) {
-       die "Error: Option $lvalue defined more than once!\n";
+       if (!$override || defined(${$overrides}{$lvalue})) {
+           my $extra = "";
+           if ($override) {
+               $extra = "In the same override section!\n";
+           }
+           die "$name: $.: Option $lvalue defined more than once!\n$extra";
+       }
+       ${$overrides}{$lvalue} = $rvalue;
     }
     if ($rvalue =~ /^\s*$/) {
        delete $opt{$lvalue};
@@ -355,86 +377,274 @@ sub set_variable {
     }
 }
 
-sub read_config {
-    my ($config) = @_;
+sub process_compare {
+    my ($lval, $cmp, $rval) = @_;
+
+    # remove whitespace
+
+    $lval =~ s/^\s*//;
+    $lval =~ s/\s*$//;
+
+    $rval =~ s/^\s*//;
+    $rval =~ s/\s*$//;
+
+    if ($cmp eq "==") {
+       return $lval eq $rval;
+    } elsif ($cmp eq "!=") {
+       return $lval ne $rval;
+    }
+
+    my $statement = "$lval $cmp $rval";
+    my $ret = eval $statement;
+
+    # $@ stores error of eval
+    if ($@) {
+       return -1;
+    }
+
+    return $ret;
+}
+
+sub value_defined {
+    my ($val) = @_;
+
+    return defined($variable{$2}) ||
+       defined($opt{$2});
+}
+
+my $d = 0;
+sub process_expression {
+    my ($name, $val) = @_;
+
+    my $c = $d++;
+
+    while ($val =~ s/\(([^\(]*?)\)/\&\&\&\&VAL\&\&\&\&/) {
+       my $express = $1;
+
+       if (process_expression($name, $express)) {
+           $val =~ s/\&\&\&\&VAL\&\&\&\&/ 1 /;
+       } else {
+           $val =~ s/\&\&\&\&VAL\&\&\&\&/ 0 /;
+       }
+    }
+
+    $d--;
+    my $OR = "\\|\\|";
+    my $AND = "\\&\\&";
+
+    while ($val =~ s/^(.*?)($OR|$AND)//) {
+       my $express = $1;
+       my $op = $2;
+
+       if (process_expression($name, $express)) {
+           if ($op eq "||") {
+               return 1;
+           }
+       } else {
+           if ($op eq "&&") {
+               return 0;
+           }
+       }
+    }
+
+    if ($val =~ /(.*)(==|\!=|>=|<=|>|<)(.*)/) {
+       my $ret = process_compare($1, $2, $3);
+       if ($ret < 0) {
+           die "$name: $.: Unable to process comparison\n";
+       }
+       return $ret;
+    }
+
+    if ($val =~ /^\s*(NOT\s*)?DEFINED\s+(\S+)\s*$/) {
+       if (defined $1) {
+           return !value_defined($2);
+       } else {
+           return value_defined($2);
+       }
+    }
+
+    if ($val =~ /^\s*0\s*$/) {
+       return 0;
+    } elsif ($val =~ /^\s*\d+\s*$/) {
+       return 1;
+    }
+
+    die ("$name: $.: Undefined content $val in if statement\n");
+}
+
+sub process_if {
+    my ($name, $value) = @_;
 
-    open(IN, $config) || die "can't read file $config";
+    # Convert variables and replace undefined ones with 0
+    my $val = process_variables($value, 1);
+    my $ret = process_expression $name, $val;
+
+    return $ret;
+}
+
+sub __read_config {
+    my ($config, $current_test_num) = @_;
+
+    my $in;
+    open($in, $config) || die "can't read file $config";
 
     my $name = $config;
     $name =~ s,.*/(.*),$1,;
 
-    my $test_num = 0;
+    my $test_num = $$current_test_num;
     my $default = 1;
     my $repeat = 1;
     my $num_tests_set = 0;
     my $skip = 0;
     my $rest;
+    my $line;
     my $test_case = 0;
+    my $if = 0;
+    my $if_set = 0;
+    my $override = 0;
 
-    while (<IN>) {
+    my %overrides;
+
+    while (<$in>) {
 
        # ignore blank lines and comments
        next if (/^\s*$/ || /\s*\#/);
 
-       if (/^\s*TEST_START(.*)/) {
+       if (/^\s*(TEST_START|DEFAULTS)\b(.*)/) {
 
-           $rest = $1;
+           my $type = $1;
+           $rest = $2;
+           $line = $2;
 
-           if ($num_tests_set) {
-               die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
-           }
+           my $old_test_num;
+           my $old_repeat;
+           $override = 0;
+
+           if ($type eq "TEST_START") {
 
-           my $old_test_num = $test_num;
-           my $old_repeat = $repeat;
+               if ($num_tests_set) {
+                   die "$name: $.: Can not specify both NUM_TESTS and TEST_START\n";
+               }
 
-           $test_num += $repeat;
-           $default = 0;
-           $repeat = 1;
+               $old_test_num = $test_num;
+               $old_repeat = $repeat;
 
-           if ($rest =~ /\s+SKIP(.*)/) {
-               $rest = $1;
+               $test_num += $repeat;
+               $default = 0;
+               $repeat = 1;
+           } else {
+               $default = 1;
+           }
+
+           # If SKIP is anywhere in the line, the command will be skipped
+           if ($rest =~ s/\s+SKIP\b//) {
                $skip = 1;
            } else {
                $test_case = 1;
                $skip = 0;
            }
 
-           if ($rest =~ /\s+ITERATE\s+(\d+)(.*)$/) {
-               $repeat = $1;
-               $rest = $2;
-               $repeat_tests{"$test_num"} = $repeat;
+           if ($rest =~ s/\sELSE\b//) {
+               if (!$if) {
+                   die "$name: $.: ELSE found with out matching IF section\n$_";
+               }
+               $if = 0;
+
+               if ($if_set) {
+                   $skip = 1;
+               } else {
+                   $skip = 0;
+               }
            }
 
-           if ($rest =~ /\s+SKIP(.*)/) {
-               $rest = $1;
-               $skip = 1;
+           if ($rest =~ s/\sIF\s+(.*)//) {
+               if (process_if($name, $1)) {
+                   $if_set = 1;
+               } else {
+                   $skip = 1;
+               }
+               $if = 1;
+           } else {
+               $if = 0;
+               $if_set = 0;
            }
 
-           if ($rest !~ /^\s*$/) {
-               die "$name: $.: Gargbage found after TEST_START\n$_";
+           if (!$skip) {
+               if ($type eq "TEST_START") {
+                   if ($rest =~ s/\s+ITERATE\s+(\d+)//) {
+                       $repeat = $1;
+                       $repeat_tests{"$test_num"} = $repeat;
+                   }
+               } elsif ($rest =~ s/\sOVERRIDE\b//) {
+                   # DEFAULT only
+                   $override = 1;
+                   # Clear previous overrides
+                   %overrides = ();
+               }
+           }
+
+           if (!$skip && $rest !~ /^\s*$/) {
+               die "$name: $.: Gargbage found after $type\n$_";
            }
 
-           if ($skip) {
+           if ($skip && $type eq "TEST_START") {
                $test_num = $old_test_num;
                $repeat = $old_repeat;
            }
 
-       } elsif (/^\s*DEFAULTS(.*)$/) {
-           $default = 1;
-
+       } elsif (/^\s*ELSE\b(.*)$/) {
+           if (!$if) {
+               die "$name: $.: ELSE found with out matching IF section\n$_";
+           }
            $rest = $1;
-
-           if ($rest =~ /\s+SKIP(.*)/) {
-               $rest = $1;
+           if ($if_set) {
                $skip = 1;
+               $rest = "";
            } else {
                $skip = 0;
+
+               if ($rest =~ /\sIF\s+(.*)/) {
+                   # May be a ELSE IF section.
+                   if (!process_if($name, $1)) {
+                       $skip = 1;
+                   }
+                   $rest = "";
+               } else {
+                   $if = 0;
+               }
            }
 
            if ($rest !~ /^\s*$/) {
                die "$name: $.: Gargbage found after DEFAULTS\n$_";
            }
 
+       } elsif (/^\s*INCLUDE\s+(\S+)/) {
+
+           next if ($skip);
+
+           if (!$default) {
+               die "$name: $.: INCLUDE can only be done in default sections\n$_";
+           }
+
+           my $file = process_variables($1);
+
+           if ($file !~ m,^/,) {
+               # check the path of the config file first
+               if ($config =~ m,(.*)/,) {
+                   if (-f "$1/$file") {
+                       $file = "$1/$file";
+                   }
+               }
+           }
+               
+           if ( ! -r $file ) {
+               die "$name: $.: Can't read file $file\n$_";
+           }
+
+           if (__read_config($file, \$test_num)) {
+               $test_case = 1;
+           }
+
        } elsif (/^\s*([A-Z_\[\]\d]+)\s*=\s*(.*?)\s*$/) {
 
            next if ($skip);
@@ -460,10 +670,10 @@ sub read_config {
            }
 
            if ($default || $lvalue =~ /\[\d+\]$/) {
-               set_value($lvalue, $rvalue);
+               set_value($lvalue, $rvalue, $override, \%overrides, $name);
            } else {
                my $val = "$lvalue\[$test_num\]";
-               set_value($val, $rvalue);
+               set_value($val, $rvalue, $override, \%overrides, $name);
 
                if ($repeat > 1) {
                    $repeats{$val} = $repeat;
@@ -490,13 +700,26 @@ sub read_config {
        }
     }
 
-    close(IN);
-
     if ($test_num) {
        $test_num += $repeat - 1;
        $opt{"NUM_TESTS"} = $test_num;
     }
 
+    close($in);
+
+    $$current_test_num = $test_num;
+
+    return $test_case;
+}
+
+sub read_config {
+    my ($config) = @_;
+
+    my $test_case;
+    my $test_num = 0;
+
+    $test_case = __read_config $config, \$test_num;
+
     # make sure we have all mandatory configs
     get_ktest_configs;
 
@@ -524,6 +747,18 @@ sub __eval_option {
     # Add space to evaluate the character before $
     $option = " $option";
     my $retval = "";
+    my $repeated = 0;
+    my $parent = 0;
+
+    foreach my $test (keys %repeat_tests) {
+       if ($i >= $test &&
+           $i < $test + $repeat_tests{$test}) {
+
+           $repeated = 1;
+           $parent = $test;
+           last;
+       }
+    }
 
     while ($option =~ /(.*?[^\\])\$\{(.*?)\}(.*)/) {
        my $start = $1;
@@ -537,10 +772,14 @@ sub __eval_option {
        # otherwise see if the default OPT (without [$i]) exists.
 
        my $o = "$var\[$i\]";
+       my $parento = "$var\[$parent\]";
 
        if (defined($opt{$o})) {
            $o = $opt{$o};
            $retval = "$retval$o";
+       } elsif ($repeated && defined($opt{$parento})) {
+           $o = $opt{$parento};
+           $retval = "$retval$o";
        } elsif (defined($opt{$var})) {
            $o = $opt{$var};
            $retval = "$retval$o";
@@ -603,8 +842,20 @@ sub doprint {
 }
 
 sub run_command;
+sub start_monitor;
+sub end_monitor;
+sub wait_for_monitor;
 
 sub reboot {
+    my ($time) = @_;
+
+    if (defined($time)) {
+       start_monitor;
+       # flush out current monitor
+       # May contain the reboot success line
+       wait_for_monitor 1;
+    }
+
     # try to reboot normally
     if (run_command $reboot) {
        if (defined($powercycle_after_reboot)) {
@@ -615,12 +866,17 @@ sub reboot {
        # nope? power cycle it.
        run_command "$power_cycle";
     }
+
+    if (defined($time)) {
+       wait_for_monitor($time, $reboot_success_line);
+       end_monitor;
+    }
 }
 
 sub do_not_reboot {
     my $i = $iteration;
 
-    return $test_type eq "build" ||
+    return $test_type eq "build" || $no_reboot ||
        ($test_type eq "patchcheck" && $opt{"PATCHCHECK_TYPE[$i]"} eq "build") ||
        ($test_type eq "bisect" && $opt{"BISECT_TYPE[$i]"} eq "build");
 }
@@ -693,16 +949,29 @@ sub end_monitor {
 }
 
 sub wait_for_monitor {
-    my ($time) = @_;
+    my ($time, $stop) = @_;
+    my $full_line = "";
     my $line;
+    my $booted = 0;
 
     doprint "** Wait for monitor to settle down **\n";
 
     # read the monitor and wait for the system to calm down
-    do {
+    while (!$booted) {
        $line = wait_for_input($monitor_fp, $time);
-       print "$line" if (defined($line));
-    } while (defined($line));
+       last if (!defined($line));
+       print "$line";
+       $full_line .= $line;
+
+       if (defined($stop) && $full_line =~ /$stop/) {
+           doprint "wait for monitor detected $stop\n";
+           $booted = 1;
+       }
+
+       if ($line =~ /\n/) {
+           $full_line = "";
+       }
+    }
     print "** Monitor flushed **\n";
 }
 
@@ -719,10 +988,7 @@ sub fail {
        # no need to reboot for just building.
        if (!do_not_reboot) {
            doprint "REBOOTING\n";
-           reboot;
-           start_monitor;
-           wait_for_monitor $sleep_time;
-           end_monitor;
+           reboot $sleep_time;
        }
 
        my $name = "";
@@ -854,9 +1120,12 @@ sub get_grub_index {
     open(IN, "$ssh_grub |")
        or die "unable to get menu.lst";
 
+    my $found = 0;
+
     while (<IN>) {
        if (/^\s*title\s+$grub_menu\s*$/) {
            $grub_number++;
+           $found = 1;
            last;
        } elsif (/^\s*title\s/) {
            $grub_number++;
@@ -865,7 +1134,7 @@ sub get_grub_index {
     close(IN);
 
     die "Could not find '$grub_menu' in /boot/grub/menu on $machine"
-       if ($grub_number < 0);
+       if (!$found);
     doprint "$grub_number\n";
 }
 
@@ -902,7 +1171,8 @@ sub wait_for_input
 
 sub reboot_to {
     if ($reboot_type eq "grub") {
-       run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch && reboot)'";
+       run_ssh "'(echo \"savedefault --default=$grub_number --once\" | grub --batch)'";
+       reboot;
        return;
     }
 
@@ -1083,6 +1353,8 @@ sub do_post_install {
 
 sub install {
 
+    return if ($no_install);
+
     run_scp "$outputdir/$build_target", "$target_image" or
        dodie "failed to copy image";
 
@@ -1140,6 +1412,11 @@ sub get_version {
 }
 
 sub start_monitor_and_boot {
+    # Make sure the stable kernel has finished booting
+    start_monitor;
+    wait_for_monitor 5;
+    end_monitor;
+
     get_grub_index;
     get_version;
     install;
@@ -1250,6 +1527,10 @@ sub build {
 
     unlink $buildlog;
 
+    # Failed builds should not reboot the target
+    my $save_no_reboot = $no_reboot;
+    $no_reboot = 1;
+
     if (defined($pre_build)) {
        my $ret = run_command $pre_build;
        if (!$ret && defined($pre_build_die) &&
@@ -1272,15 +1553,15 @@ sub build {
        # allow for empty configs
        run_command "touch $output_config";
 
-       run_command "mv $output_config $outputdir/config_temp" or
-           dodie "moving .config";
+       if (!$noclean) {
+           run_command "mv $output_config $outputdir/config_temp" or
+               dodie "moving .config";
 
-       if (!$noclean && !run_command "$make mrproper") {
-           dodie "make mrproper";
-       }
+           run_command "$make mrproper" or dodie "make mrproper";
 
-       run_command "mv $outputdir/config_temp $output_config" or
-           dodie "moving config_temp";
+           run_command "mv $outputdir/config_temp $output_config" or
+               dodie "moving config_temp";
+       }
 
     } elsif (!$noclean) {
        unlink "$output_config";
@@ -1318,10 +1599,15 @@ sub build {
 
     if (!$build_ret) {
        # bisect may need this to pass
-       return 0 if ($in_bisect);
+       if ($in_bisect) {
+           $no_reboot = $save_no_reboot;
+           return 0;
+       }
        fail "failed build" and return 0;
     }
 
+    $no_reboot = $save_no_reboot;
+
     return 1;
 }
 
@@ -1356,10 +1642,7 @@ sub success {
 
     if ($i != $opt{"NUM_TESTS"} && !do_not_reboot) {
        doprint "Reboot and wait $sleep_time seconds\n";
-       reboot;
-       start_monitor;
-       wait_for_monitor $sleep_time;
-       end_monitor;
+       reboot $sleep_time;
     }
 }
 
@@ -1500,10 +1783,7 @@ sub run_git_bisect {
 
 sub bisect_reboot {
     doprint "Reboot and sleep $bisect_sleep_time seconds\n";
-    reboot;
-    start_monitor;
-    wait_for_monitor $bisect_sleep_time;
-    end_monitor;
+    reboot $bisect_sleep_time;
 }
 
 # returns 1 on success, 0 on failure, -1 on skip
@@ -2066,10 +2346,7 @@ sub config_bisect {
 
 sub patchcheck_reboot {
     doprint "Reboot and sleep $patchcheck_sleep_time seconds\n";
-    reboot;
-    start_monitor;
-    wait_for_monitor $patchcheck_sleep_time;
-    end_monitor;
+    reboot $patchcheck_sleep_time;
 }
 
 sub patchcheck {
@@ -2178,12 +2455,31 @@ sub patchcheck {
 }
 
 my %depends;
+my %depcount;
 my $iflevel = 0;
 my @ifdeps;
 
 # prevent recursion
 my %read_kconfigs;
 
+sub add_dep {
+    # $config depends on $dep
+    my ($config, $dep) = @_;
+
+    if (defined($depends{$config})) {
+       $depends{$config} .= " " . $dep;
+    } else {
+       $depends{$config} = $dep;
+    }
+
+    # record the number of configs depending on $dep
+    if (defined $depcount{$dep}) {
+       $depcount{$dep}++;
+    } else {
+       $depcount{$dep} = 1;
+    } 
+}
+
 # taken from streamline_config.pl
 sub read_kconfig {
     my ($kconfig) = @_;
@@ -2230,30 +2526,19 @@ sub read_kconfig {
            $config = $2;
 
            for (my $i = 0; $i < $iflevel; $i++) {
-               if ($i) {
-                   $depends{$config} .= " " . $ifdeps[$i];
-               } else {
-                   $depends{$config} = $ifdeps[$i];
-               }
-               $state = "DEP";
+               add_dep $config, $ifdeps[$i];
            }
 
        # collect the depends for the config
        } elsif ($state eq "NEW" && /^\s*depends\s+on\s+(.*)$/) {
 
-           if (defined($depends{$1})) {
-               $depends{$config} .= " " . $1;
-           } else {
-               $depends{$config} = $1;
-           }
+           add_dep $config, $1;
 
        # Get the configs that select this config
-       } elsif ($state ne "NONE" && /^\s*select\s+(\S+)/) {
-           if (defined($depends{$1})) {
-               $depends{$1} .= " " . $config;
-           } else {
-               $depends{$1} = $config;
-           }
+       } elsif ($state eq "NEW" && /^\s*select\s+(\S+)/) {
+
+           # selected by depends on config
+           add_dep $1, $config;
 
        # Check for if statements
        } elsif (/^if\s+(.*\S)\s*$/) {
@@ -2365,11 +2650,18 @@ sub make_new_config {
     close OUT;
 }
 
+sub chomp_config {
+    my ($config) = @_;
+
+    $config =~ s/CONFIG_//;
+
+    return $config;
+}
+
 sub get_depends {
     my ($dep) = @_;
 
-    my $kconfig = $dep;
-    $kconfig =~ s/CONFIG_//;
+    my $kconfig = chomp_config $dep;
 
     $dep = $depends{"$kconfig"};
 
@@ -2419,8 +2711,7 @@ sub test_this_config {
        return undef;
     }
 
-    my $kconfig = $config;
-    $kconfig =~ s/CONFIG_//;
+    my $kconfig = chomp_config $config;
 
     # Test dependencies first
     if (defined($depends{"$kconfig"})) {
@@ -2510,6 +2801,14 @@ sub make_min_config {
 
     my @config_keys = keys %min_configs;
 
+    # All configs need a depcount
+    foreach my $config (@config_keys) {
+       my $kconfig = chomp_config $config;
+       if (!defined $depcount{$kconfig}) {
+               $depcount{$kconfig} = 0;
+       }
+    }
+
     # Remove anything that was set by the make allnoconfig
     # we shouldn't need them as they get set for us anyway.
     foreach my $config (@config_keys) {
@@ -2548,8 +2847,13 @@ sub make_min_config {
        # Now disable each config one by one and do a make oldconfig
        # till we find a config that changes our list.
 
-       # Put configs that did not modify the config at the end.
        my @test_configs = keys %min_configs;
+
+       # Sort keys by who is most dependent on
+       @test_configs = sort  { $depcount{chomp_config($b)} <=> $depcount{chomp_config($a)} }
+                         @test_configs ;
+
+       # Put configs that did not modify the config at the end.
        my $reset = 1;
        for (my $i = 0; $i < $#test_configs; $i++) {
            if (!defined($nochange_config{$test_configs[0]})) {
@@ -2659,10 +2963,7 @@ sub make_min_config {
        }
 
        doprint "Reboot and wait $sleep_time seconds\n";
-       reboot;
-       start_monitor;
-       wait_for_monitor $sleep_time;
-       end_monitor;
+       reboot $sleep_time;
     }
 
     success $i;
@@ -2783,6 +3084,9 @@ sub set_test_option {
 # First we need to do is the builds
 for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
+    # Do not reboot on failing test options
+    $no_reboot = 1;
+
     $iteration = $i;
 
     my $makecmd = set_test_option("MAKE_CMD", $i);
@@ -2811,6 +3115,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $reboot_type = set_test_option("REBOOT_TYPE", $i);
     $grub_menu = set_test_option("GRUB_MENU", $i);
     $post_install = set_test_option("POST_INSTALL", $i);
+    $no_install = set_test_option("NO_INSTALL", $i);
     $reboot_script = set_test_option("REBOOT_SCRIPT", $i);
     $reboot_on_error = set_test_option("REBOOT_ON_ERROR", $i);
     $poweroff_on_error = set_test_option("POWEROFF_ON_ERROR", $i);
@@ -2832,6 +3137,7 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
     $console = set_test_option("CONSOLE", $i);
     $detect_triplefault = set_test_option("DETECT_TRIPLE_FAULT", $i);
     $success_line = set_test_option("SUCCESS_LINE", $i);
+    $reboot_success_line = set_test_option("REBOOT_SUCCESS_LINE", $i);
     $stop_after_success = set_test_option("STOP_AFTER_SUCCESS", $i);
     $stop_after_failure = set_test_option("STOP_AFTER_FAILURE", $i);
     $stop_test_after = set_test_option("STOP_TEST_AFTER", $i);
@@ -2850,9 +3156,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
 
     chdir $builddir || die "can't change directory to $builddir";
 
-    if (!-d $tmpdir) {
-       mkpath($tmpdir) or
-           die "can't create $tmpdir";
+    foreach my $dir ($tmpdir, $outputdir) {
+       if (!-d $dir) {
+           mkpath($dir) or
+               die "can't create $dir";
+       }
     }
 
     $ENV{"SSH_USER"} = $ssh_user;
@@ -2889,8 +3197,11 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
        $run_type = "ERROR";
     }
 
+    my $installme = "";
+    $installme = " no_install" if ($no_install);
+
     doprint "\n\n";
-    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type\n\n";
+    doprint "RUNNING TEST $i of $opt{NUM_TESTS} with option $test_type $run_type$installme\n\n";
 
     unlink $dmesg;
     unlink $buildlog;
@@ -2911,6 +3222,9 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
            die "failed to checkout $checkout";
     }
 
+    $no_reboot = 0;
+
+
     if ($test_type eq "bisect") {
        bisect $i;
        next;
@@ -2929,6 +3243,13 @@ for (my $i = 1; $i <= $opt{"NUM_TESTS"}; $i++) {
        build $build_type or next;
     }
 
+    if ($test_type eq "install") {
+       get_version;
+       install;
+       success $i;
+       next;
+    }
+
     if ($test_type ne "build") {
        my $failed = 0;
        start_monitor_and_boot or $failed = 1;
index b8bcd14..dbedfa1 100644 (file)
 # the same option name under the same test or as default
 # ktest will fail to execute, and no tests will run.
 #
+# DEFAULTS OVERRIDE
+#
+# Options defined in the DEFAULTS section can not be duplicated
+# even if they are defined in two different DEFAULT sections.
+# This is done to catch mistakes where an option is added but
+# the previous option was forgotten about and not commented.
+#
+# The OVERRIDE keyword can be added to a section to allow this
+# section to override other DEFAULT sections values that have
+# been defined previously. It will only override options that
+# have been defined before its use. Options defined later
+# in a non override section will still error. The same option
+# can not be defined in the same section even if that section
+# is marked OVERRIDE.
+#
+#
+#
+# Both TEST_START and DEFAULTS sections can also have the IF keyword
+# The value after the IF must evaluate into a 0 or non 0 positive
+# integer, and can use the config variables (explained below).
+#
+# DEFAULTS IF ${IS_X86_32}
+#
+# The above will process the DEFAULTS section if the config
+# variable IS_X86_32 evaluates to a non zero positive integer
+# otherwise if it evaluates to zero, it will act the same
+# as if the SKIP keyword was used.
+#
+# The ELSE keyword can be used directly after a section with
+# a IF statement.
+#
+# TEST_START IF ${RUN_NET_TESTS}
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
+#
+# ELSE
+#
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-normal
+#
+#
+# The ELSE keyword can also contain an IF statement to allow multiple
+# if then else sections. But all the sections must be either
+# DEFAULT or TEST_START, they can not be a mixture.
+#
+# TEST_START IF ${RUN_NET_TESTS}
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
+#
+# ELSE IF ${RUN_DISK_TESTS}
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-tests
+#
+# ELSE IF ${RUN_CPU_TESTS}
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-cpu
+#
+# ELSE
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-network
+#
+# The if statement may also have comparisons that will and for
+# == and !=, strings may be used for both sides.
+#
+# BOX_TYPE := x86_32
+#
+# DEFAULTS IF ${BOX_TYPE} == x86_32
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-32
+# ELSE
+# BUILD_TYPE = useconfig:${CONFIG_DIR}/config-64
+#
+# The DEFINED keyword can be used by the IF statements too.
+# It returns true if the given config variable or option has been defined
+# or false otherwise.
+#
+# 
+# DEFAULTS IF DEFINED USE_CC
+# CC := ${USE_CC}
+# ELSE
+# CC := gcc
+#
+#
+# As well as NOT DEFINED.
+#
+# DEFAULTS IF NOT DEFINED MAKE_CMD
+# MAKE_CMD := make ARCH=x86
+#
+#
+# And/or ops (&&,||) may also be used to make complex conditionals.
+#
+# TEST_START IF (DEFINED ALL_TESTS || ${MYTEST} == boottest) && ${MACHINE} == gandalf
+#
+# Notice the use of paranthesis. Without any paranthesis the above would be
+# processed the same as:
+#
+# TEST_START IF DEFINED ALL_TESTS || (${MYTEST} == boottest && ${MACHINE} == gandalf)
+#
+#
+#
+# INCLUDE file
+#
+# The INCLUDE keyword may be used in DEFAULT sections. This will
+# read another config file and process that file as well. The included
+# file can include other files, add new test cases or default
+# statements. Config variables will be passed to these files and changes
+# to config variables will be seen by top level config files. Including
+# a file is processed just like the contents of the file was cut and pasted
+# into the top level file, except, that include files that end with
+# TEST_START sections will have that section ended at the end of
+# the include file. That is, an included file is included followed
+# by another DEFAULT keyword.
+#
+# Unlike other files referenced in this config, the file path does not need
+# to be absolute. If the file does not start with '/', then the directory
+# that the current config file was located in is used. If no config by the
+# given name is found there, then the current directory is searched.
+#
+# INCLUDE myfile
+# DEFAULT
+#
+# is the same as:
+#
+# INCLUDE myfile
+#
+# Note, if the include file does not contain a full path, the file is
+# searched first by the location of the original include file, and then
+# by the location that ktest.pl was executed in.
+#
 
 #### Config variables ####
 #
 
 # The default test type (default test)
 # The test types may be:
-#   build - only build the kernel, do nothing else
-#   boot - build and boot the kernel
-#   test - build, boot and if TEST is set, run the test script
+#   build   - only build the kernel, do nothing else
+#   install - build and install, but do nothing else (does not reboot)
+#   boot    - build, install, and boot the kernel
+#   test    - build, boot and if TEST is set, run the test script
 #          (If TEST is not set, it defaults back to boot)
 #   bisect - Perform a bisect on the kernel (see BISECT_TYPE below)
 #   patchcheck - Do a test on a series of commits in git (see PATCHCHECK below)
 # or on some systems:
 #POST_INSTALL = ssh user@target /sbin/dracut -f /boot/initramfs-test.img $KERNEL_VERSION
 
+# If for some reason you just want to boot the kernel and you do not
+# want the test to install anything new. For example, you may just want
+# to boot test the same kernel over and over and do not want to go through
+# the hassle of installing anything, you can set this option to 1
+# (default 0)
+#NO_INSTALL = 1
+
 # If there is a script that you require to run before the build is done
 # you can specify it with PRE_BUILD.
 #
 # (default "login:")
 #SUCCESS_LINE = login:
 
+# To speed up between reboots, defining a line that the
+# default kernel produces that represents that the default
+# kernel has successfully booted and can be used to pass
+# a new test kernel to it. Otherwise ktest.pl will wait till
+# SLEEP_TIME to continue.
+# (default undefined)
+#REBOOT_SUCCESS_LINE = login:
+
 # In case the console constantly fills the screen, having
 # a specified time to stop the test after success is recommended.
 # (in seconds)
 # another test. If a reboot to the reliable kernel happens,
 # we wait SLEEP_TIME for the console to stop producing output
 # before starting the next test.
+#
+# You can speed up reboot times even more by setting REBOOT_SUCCESS_LINE.
 # (default 60)
 #SLEEP_TIME = 60