aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CREDITS1
-rw-r--r--Documentation/ABI/testing/sysfs-firmware-memmap2
-rw-r--r--Documentation/DocBook/Makefile2
-rw-r--r--Documentation/DocBook/device-drivers.tmpl418
-rw-r--r--Documentation/DocBook/kernel-api.tmpl377
-rw-r--r--Documentation/PCI/PCIEBUS-HOWTO.txt2
-rw-r--r--Documentation/cgroups/cgroups.txt6
-rw-r--r--Documentation/cgroups/cpusets.txt65
-rw-r--r--Documentation/driver-model/device.txt8
-rw-r--r--Documentation/filesystems/sysfs.txt50
-rw-r--r--Documentation/hwmon/hpfall.c101
-rw-r--r--Documentation/hwmon/lis3lv02d8
-rw-r--r--Documentation/kernel-parameters.txt6
-rw-r--r--Documentation/tracers/mmiotrace.txt6
-rw-r--r--MAINTAINERS29
-rw-r--r--Makefile4
-rw-r--r--README2
-rw-r--r--arch/alpha/kernel/process.c8
-rw-r--r--arch/alpha/kernel/smp.c12
-rw-r--r--arch/arm/configs/at91sam9260ek_defconfig2
-rw-r--r--arch/arm/configs/at91sam9261ek_defconfig2
-rw-r--r--arch/arm/configs/at91sam9263ek_defconfig2
-rw-r--r--arch/arm/configs/at91sam9rlek_defconfig2
-rw-r--r--arch/arm/configs/qil-a9260_defconfig2
-rw-r--r--arch/arm/kernel/elf.c4
-rw-r--r--arch/arm/mach-at91/at91cap9_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c2
-rw-r--r--arch/arm/mach-at91/at91sam9rl_devices.c2
-rw-r--r--arch/arm/mach-at91/gpio.c15
-rw-r--r--arch/arm/mach-at91/include/mach/board.h1
-rw-r--r--arch/arm/mach-ep93xx/include/mach/gesbc9312.h3
-rw-r--r--arch/arm/mach-ep93xx/include/mach/hardware.h1
-rw-r--r--arch/arm/mach-kirkwood/irq.c2
-rw-r--r--arch/arm/mach-mv78xx0/irq.c2
-rw-r--r--arch/arm/mach-omap2/clock.c16
-rw-r--r--arch/arm/mach-orion5x/irq.c2
-rw-r--r--arch/arm/mm/mmu.c3
-rw-r--r--arch/arm/plat-orion/gpio.c73
-rw-r--r--arch/arm/plat-orion/include/plat/gpio.h3
-rw-r--r--arch/avr32/mach-at32ap/include/mach/board.h1
-rw-r--r--arch/ia64/Kconfig7
-rw-r--r--arch/ia64/configs/xen_domu_defconfig1601
-rw-r--r--arch/ia64/include/asm/kvm.h4
-rw-r--r--arch/ia64/include/asm/mmzone.h4
-rw-r--r--arch/ia64/include/asm/sn/bte.h2
-rw-r--r--arch/ia64/kernel/smpboot.c5
-rw-r--r--arch/ia64/kvm/kvm-ia64.c4
-rw-r--r--arch/ia64/kvm/process.c17
-rw-r--r--arch/ia64/mm/numa.c4
-rw-r--r--arch/ia64/sn/kernel/bte.c7
-rw-r--r--arch/ia64/xen/Kconfig3
-rw-r--r--arch/ia64/xen/xen_pv_ops.c4
-rw-r--r--arch/m68k/atari/ataints.c16
-rw-r--r--arch/m68k/atari/atakeyb.c4
-rw-r--r--arch/m68k/atari/config.c2
-rw-r--r--arch/m68k/atari/debug.c22
-rw-r--r--arch/m68k/atari/time.c8
-rw-r--r--arch/m68k/include/asm/atarihw.h4
-rw-r--r--arch/m68k/include/asm/atariints.h6
-rw-r--r--arch/mn10300/Kconfig1
-rw-r--r--arch/mn10300/unit-asb2305/pci.c2
-rw-r--r--arch/powerpc/include/asm/pgtable-4k.h2
-rw-r--r--arch/powerpc/include/asm/pgtable-64k.h2
-rw-r--r--arch/powerpc/include/asm/pgtable-ppc32.h3
-rw-r--r--arch/powerpc/kernel/align.c7
-rw-r--r--arch/powerpc/kvm/powerpc.c4
-rw-r--r--arch/powerpc/mm/numa.c5
-rw-r--r--arch/powerpc/platforms/ps3/mm.c2
-rw-r--r--arch/s390/include/asm/cputime.h2
-rw-r--r--arch/s390/include/asm/setup.h2
-rw-r--r--arch/s390/kernel/setup.c9
-rw-r--r--arch/s390/kvm/kvm-s390.c4
-rw-r--r--arch/um/drivers/vde_user.c6
-rw-r--r--arch/x86/Kconfig58
-rw-r--r--arch/x86/Kconfig.debug24
-rw-r--r--arch/x86/boot/Makefile1
-rw-r--r--arch/x86/boot/a20.c6
-rw-r--r--arch/x86/boot/boot.h3
-rw-r--r--arch/x86/boot/compressed/head_32.S2
-rw-r--r--arch/x86/boot/compressed/head_64.S4
-rw-r--r--arch/x86/boot/header.S2
-rw-r--r--arch/x86/boot/main.c5
-rw-r--r--arch/x86/boot/voyager.c40
-rw-r--r--arch/x86/configs/i386_defconfig1
-rw-r--r--arch/x86/configs/x86_64_defconfig1
-rw-r--r--arch/x86/ia32/ia32_signal.c70
-rw-r--r--arch/x86/include/asm/apic.h396
-rw-r--r--arch/x86/include/asm/arch_hooks.h26
-rw-r--r--arch/x86/include/asm/genapic.h264
-rw-r--r--arch/x86/include/asm/i8259.h4
-rw-r--r--arch/x86/include/asm/io.h11
-rw-r--r--arch/x86/include/asm/ipi.h2
-rw-r--r--arch/x86/include/asm/kvm.h7
-rw-r--r--arch/x86/include/asm/mach-voyager/do_timer.h17
-rw-r--r--arch/x86/include/asm/mach-voyager/entry_arch.h26
-rw-r--r--arch/x86/include/asm/mach-voyager/setup_arch.h12
-rw-r--r--arch/x86/include/asm/mmzone_32.h2
-rw-r--r--arch/x86/include/asm/mmzone_64.h2
-rw-r--r--arch/x86/include/asm/mpspec.h2
-rw-r--r--arch/x86/include/asm/page_32_types.h2
-rw-r--r--arch/x86/include/asm/page_64_types.h2
-rw-r--r--arch/x86/include/asm/page_types.h6
-rw-r--r--arch/x86/include/asm/pgtable-2level_types.h2
-rw-r--r--arch/x86/include/asm/pgtable-3level_types.h2
-rw-r--r--arch/x86/include/asm/pgtable_64_types.h1
-rw-r--r--arch/x86/include/asm/pgtable_types.h6
-rw-r--r--arch/x86/include/asm/processor.h10
-rw-r--r--arch/x86/include/asm/setup.h11
-rw-r--r--arch/x86/include/asm/syscalls.h2
-rw-r--r--arch/x86/include/asm/timer.h2
-rw-r--r--arch/x86/include/asm/vic.h61
-rw-r--r--arch/x86/include/asm/voyager.h571
-rw-r--r--arch/x86/kernel/Makefile33
-rw-r--r--arch/x86/kernel/acpi/boot.c1
-rw-r--r--arch/x86/kernel/acpi/realmode/wakeup.S4
-rw-r--r--arch/x86/kernel/acpi/wakeup_32.S2
-rw-r--r--arch/x86/kernel/acpi/wakeup_64.S34
-rw-r--r--arch/x86/kernel/apic/Makefile19
-rw-r--r--arch/x86/kernel/apic/apic.c (renamed from arch/x86/kernel/apic.c)92
-rw-r--r--arch/x86/kernel/apic/apic_flat_64.c (renamed from arch/x86/kernel/genapic_flat_64.c)22
-rw-r--r--arch/x86/kernel/apic/bigsmp_32.c (renamed from arch/x86/kernel/bigsmp_32.c)54
-rw-r--r--arch/x86/kernel/apic/es7000_32.c (renamed from arch/x86/kernel/es7000_32.c)442
-rw-r--r--arch/x86/kernel/apic/io_apic.c (renamed from arch/x86/kernel/io_apic.c)2
-rw-r--r--arch/x86/kernel/apic/ipi.c (renamed from arch/x86/kernel/ipi.c)0
-rw-r--r--arch/x86/kernel/apic/nmi.c (renamed from arch/x86/kernel/nmi.c)0
-rw-r--r--arch/x86/kernel/apic/numaq_32.c (renamed from arch/x86/kernel/numaq_32.c)293
-rw-r--r--arch/x86/kernel/apic/probe_32.c (renamed from arch/x86/kernel/probe_32.c)222
-rw-r--r--arch/x86/kernel/apic/probe_64.c (renamed from arch/x86/kernel/genapic_64.c)38
-rw-r--r--arch/x86/kernel/apic/summit_32.c (renamed from arch/x86/kernel/summit_32.c)25
-rw-r--r--arch/x86/kernel/apic/x2apic_cluster.c (renamed from arch/x86/kernel/genx2apic_cluster.c)19
-rw-r--r--arch/x86/kernel/apic/x2apic_phys.c (renamed from arch/x86/kernel/genx2apic_phys.c)24
-rw-r--r--arch/x86/kernel/apic/x2apic_uv_x.c (renamed from arch/x86/kernel/genx2apic_uv_x.c)12
-rw-r--r--arch/x86/kernel/apm_32.c4
-rw-r--r--arch/x86/kernel/cpu/addon_cpuid_features.c2
-rw-r--r--arch/x86/kernel/cpu/amd.c2
-rw-r--r--arch/x86/kernel/cpu/common.c8
-rw-r--r--arch/x86/kernel/cpu/cpufreq/e_powersaver.c6
-rw-r--r--arch/x86/kernel/cpu/cpufreq/powernow-k8.c12
-rw-r--r--arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c6
-rw-r--r--arch/x86/kernel/cpu/intel.c5
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_64.c7
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd_64.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_intel_64.c10
-rw-r--r--arch/x86/kernel/cpu/mcheck/p4.c4
-rw-r--r--arch/x86/kernel/cpu/perfctr-watchdog.c2
-rw-r--r--arch/x86/kernel/crash.c2
-rw-r--r--arch/x86/kernel/efi_stub_32.S2
-rw-r--r--arch/x86/kernel/entry_32.S4
-rw-r--r--arch/x86/kernel/entry_64.S2
-rw-r--r--arch/x86/kernel/head_32.S4
-rw-r--r--arch/x86/kernel/i8259.c1
-rw-r--r--arch/x86/kernel/irq_32.c1
-rw-r--r--arch/x86/kernel/irqinit_32.c13
-rw-r--r--arch/x86/kernel/kgdb.c2
-rw-r--r--arch/x86/kernel/kvmclock.c1
-rw-r--r--arch/x86/kernel/machine_kexec_32.c2
-rw-r--r--arch/x86/kernel/mca_32.c5
-rw-r--r--arch/x86/kernel/mpparse.c17
-rw-r--r--arch/x86/kernel/paravirt.c1
-rw-r--r--arch/x86/kernel/process_32.c3
-rw-r--r--arch/x86/kernel/ptrace.c2
-rw-r--r--arch/x86/kernel/reboot.c2
-rw-r--r--arch/x86/kernel/relocate_kernel_32.S2
-rw-r--r--arch/x86/kernel/relocate_kernel_64.S4
-rw-r--r--arch/x86/kernel/setup.c103
-rw-r--r--arch/x86/kernel/smp.c2
-rw-r--r--arch/x86/kernel/smpboot.c18
-rw-r--r--arch/x86/kernel/time_32.c6
-rw-r--r--arch/x86/kernel/time_64.c2
-rw-r--r--arch/x86/kernel/tlb_uv.c4
-rw-r--r--arch/x86/kernel/trampoline_32.S2
-rw-r--r--arch/x86/kernel/trampoline_64.S4
-rw-r--r--arch/x86/kernel/traps.c6
-rw-r--r--arch/x86/kernel/visws_quirks.c8
-rw-r--r--arch/x86/kernel/vmi_32.c4
-rw-r--r--arch/x86/kernel/vmiclock_32.c7
-rw-r--r--arch/x86/kernel/vmlinux_32.lds.S2
-rw-r--r--arch/x86/kernel/vmlinux_64.lds.S2
-rw-r--r--arch/x86/kvm/i8254.c2
-rw-r--r--arch/x86/kvm/irq.c7
-rw-r--r--arch/x86/kvm/irq.h1
-rw-r--r--arch/x86/kvm/lapic.c66
-rw-r--r--arch/x86/kvm/lapic.h2
-rw-r--r--arch/x86/kvm/mmu.c9
-rw-r--r--arch/x86/kvm/svm.c1
-rw-r--r--arch/x86/kvm/vmx.c5
-rw-r--r--arch/x86/kvm/x86.c10
-rw-r--r--arch/x86/lguest/Kconfig1
-rw-r--r--arch/x86/lguest/boot.c17
-rw-r--r--arch/x86/lib/getuser.S2
-rw-r--r--arch/x86/mach-voyager/Makefile8
-rw-r--r--arch/x86/mach-voyager/setup.c119
-rw-r--r--arch/x86/mach-voyager/voyager_basic.c317
-rw-r--r--arch/x86/mach-voyager/voyager_cat.c1197
-rw-r--r--arch/x86/mach-voyager/voyager_smp.c1805
-rw-r--r--arch/x86/mach-voyager/voyager_thread.c128
-rw-r--r--arch/x86/mm/fault.c1078
-rw-r--r--arch/x86/mm/numa_32.c2
-rw-r--r--arch/x86/mm/numa_64.c2
-rw-r--r--arch/x86/mm/pageattr.c22
-rw-r--r--arch/x86/mm/srat_64.c2
-rw-r--r--arch/x86/mm/tlb.c1
-rw-r--r--arch/x86/pci/numaq_32.c2
-rw-r--r--arch/x86/power/hibernate_asm_32.S2
-rw-r--r--arch/x86/power/hibernate_asm_64.S2
-rw-r--r--arch/x86/vdso/vma.c4
-rw-r--r--arch/x86/xen/Kconfig2
-rw-r--r--arch/x86/xen/enlighten.c19
-rw-r--r--arch/x86/xen/xen-head.S2
-rw-r--r--block/blk-timeout.c9
-rw-r--r--block/blktrace.c2
-rw-r--r--block/bsg.c17
-rw-r--r--block/genhd.c8
-rw-r--r--crypto/lrw.c8
-rw-r--r--drivers/acpi/Kconfig7
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/battery.c25
-rw-r--r--drivers/acpi/ec.c9
-rw-r--r--drivers/acpi/osl.c4
-rw-r--r--drivers/ata/libata-sff.c28
-rw-r--r--drivers/ata/pata_via.c4
-rw-r--r--drivers/ata/sata_nv.c14
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/dd.c17
-rw-r--r--drivers/base/power/main.c3
-rw-r--r--drivers/base/sys.c7
-rw-r--r--drivers/block/aoe/aoe.h1
-rw-r--r--drivers/block/aoe/aoenet.c2
-rw-r--r--drivers/block/ataflop.c4
-rw-r--r--drivers/block/cciss.c215
-rw-r--r--drivers/block/floppy.c79
-rw-r--r--drivers/block/paride/pg.c2
-rw-r--r--drivers/char/scc.h2
-rw-r--r--drivers/char/sx.c5
-rw-r--r--drivers/dma/dmaengine.c2
-rw-r--r--drivers/dma/dw_dmac.c5
-rw-r--r--drivers/dma/dw_dmac_regs.h2
-rw-r--r--drivers/firmware/memmap.c2
-rw-r--r--drivers/gpu/drm/Kconfig13
-rw-r--r--drivers/gpu/drm/drm_crtc.c3
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c21
-rw-r--r--drivers/gpu/drm/drm_fops.c3
-rw-r--r--drivers/gpu/drm/drm_gem.c79
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c25
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h3
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c182
-rw-r--r--drivers/gpu/drm/i915/i915_gem_tiling.c6
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c8
-rw-r--r--drivers/gpu/drm/i915/intel_display.c161
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c8
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c2
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c2
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_cp.c21
-rw-r--r--drivers/hid/hid-core.c13
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/hid/hidraw.c14
-rw-r--r--drivers/hwmon/f71882fg.c4
-rw-r--r--drivers/hwmon/hp_accel.c85
-rw-r--r--drivers/hwmon/lis3lv02d.c195
-rw-r--r--drivers/hwmon/lis3lv02d.h21
-rw-r--r--drivers/hwmon/vt1211.c2
-rw-r--r--drivers/hwmon/w83627ehf.c2
-rw-r--r--drivers/lguest/Kconfig2
-rw-r--r--drivers/md/dm-io.c2
-rw-r--r--drivers/md/dm-kcopyd.c2
-rw-r--r--drivers/md/md.c4
-rw-r--r--drivers/media/common/tuners/tuner-simple.c10
-rw-r--r--drivers/media/dvb/dvb-core/dmxdev.c16
-rw-r--r--drivers/media/dvb/dvb-core/dvb_demux.c16
-rw-r--r--drivers/media/radio/radio-si470x.c55
-rw-r--r--drivers/media/video/gspca/gspca.c5
-rw-r--r--drivers/media/video/ivtv/ivtv-ioctl.c26
-rw-r--r--drivers/mfd/htc-egpio.c4
-rw-r--r--drivers/mfd/pcf50633-core.c1
-rw-r--r--drivers/mfd/sm501.c26
-rw-r--r--drivers/mfd/twl4030-core.c2
-rw-r--r--drivers/mfd/wm8350-core.c48
-rw-r--r--drivers/mfd/wm8350-regmap.c2
-rw-r--r--drivers/mmc/card/block.c2
-rw-r--r--drivers/mmc/card/mmc_test.c2
-rw-r--r--drivers/mmc/host/atmel-mci.c5
-rw-r--r--drivers/mmc/host/omap_hsmmc.c98
-rw-r--r--drivers/mmc/host/s3cmci.c2
-rw-r--r--drivers/mmc/host/sdhci-pci.c3
-rw-r--r--drivers/mmc/host/sdhci.c7
-rw-r--r--drivers/mmc/host/sdhci.h3
-rw-r--r--drivers/mtd/nand/atmel_nand.c3
-rw-r--r--drivers/parport/parport_atari.c6
-rw-r--r--drivers/pci/intel-iommu.c16
-rw-r--r--drivers/pci/msi.c10
-rw-r--r--drivers/pci/pci.c13
-rw-r--r--drivers/pci/pci.h20
-rw-r--r--drivers/pci/rom.c1
-rw-r--r--drivers/platform/x86/Kconfig2
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c25
-rw-r--r--drivers/s390/char/sclp.c5
-rw-r--r--drivers/s390/char/sclp_cmd.c5
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c15
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h2
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c1
-rw-r--r--drivers/scsi/libiscsi.c3
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c13
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h5
-rw-r--r--drivers/scsi/qla2xxx/qla_devtbl.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h9
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c7
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c58
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c40
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c12
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c16
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c2
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h2
-rw-r--r--drivers/scsi/scsi_scan.c1
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/serial/8250.c15
-rw-r--r--drivers/serial/8250_pci.c36
-rw-r--r--drivers/serial/atmel_serial.c4
-rw-r--r--drivers/serial/jsm/jsm_driver.c3
-rw-r--r--drivers/spi/spi_gpio.c2
-rw-r--r--drivers/usb/core/hcd-pci.c15
-rw-r--r--drivers/usb/core/hcd.h1
-rw-r--r--drivers/usb/gadget/pxa25x_udc.c4
-rw-r--r--drivers/usb/host/ehci-pci.c1
-rw-r--r--drivers/usb/host/ohci-pci.c1
-rw-r--r--drivers/usb/host/uhci-hcd.c1
-rw-r--r--drivers/usb/host/whci/asl.c4
-rw-r--r--drivers/usb/host/whci/pzl.c4
-rw-r--r--drivers/video/Kconfig10
-rw-r--r--drivers/video/atafb.c22
-rw-r--r--drivers/video/aty/aty128fb.c1
-rw-r--r--drivers/watchdog/Kconfig2
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c4
-rw-r--r--drivers/watchdog/at91sam9_wdt.c1
-rw-r--r--drivers/watchdog/iTCO_vendor_support.c32
-rw-r--r--drivers/watchdog/iTCO_wdt.c35
-rw-r--r--drivers/xen/manage.c8
-rw-r--r--fs/bio.c5
-rw-r--r--fs/btrfs/ctree.c58
-rw-r--r--fs/btrfs/ctree.h11
-rw-r--r--fs/btrfs/disk-io.c46
-rw-r--r--fs/btrfs/disk-io.h10
-rw-r--r--fs/btrfs/extent-tree.c83
-rw-r--r--fs/btrfs/extent_io.c2
-rw-r--r--fs/btrfs/file.c8
-rw-r--r--fs/btrfs/inode-map.c1
-rw-r--r--fs/btrfs/inode.c4
-rw-r--r--fs/btrfs/locking.c11
-rw-r--r--fs/btrfs/super.c5
-rw-r--r--fs/btrfs/transaction.c2
-rw-r--r--fs/btrfs/tree-log.c2
-rw-r--r--fs/btrfs/volumes.c6
-rw-r--r--fs/buffer.c3
-rw-r--r--fs/cifs/CHANGES15
-rw-r--r--fs/cifs/cifsfs.h2
-rw-r--r--fs/cifs/cifsglob.h6
-rw-r--r--fs/cifs/cifsproto.h4
-rw-r--r--fs/cifs/cifssmb.c7
-rw-r--r--fs/cifs/connect.c51
-rw-r--r--fs/cifs/dir.c307
-rw-r--r--fs/cifs/inode.c104
-rw-r--r--fs/cifs/readdir.c58
-rw-r--r--fs/cifs/sess.c91
-rw-r--r--fs/compat_ioctl.c2
-rw-r--r--fs/ext4/ext4.h2
-rw-r--r--fs/ext4/inode.c27
-rw-r--r--fs/ext4/mballoc.c32
-rw-r--r--fs/ext4/migrate.c8
-rw-r--r--fs/ext4/super.c11
-rw-r--r--fs/jbd2/journal.c17
-rw-r--r--fs/jbd2/transaction.c42
-rw-r--r--fs/namespace.c6
-rw-r--r--fs/notify/inotify/inotify.c2
-rw-r--r--fs/ocfs2/journal.h6
-rw-r--r--fs/seq_file.c36
-rw-r--r--fs/super.c17
-rw-r--r--fs/timerfd.c12
-rw-r--r--fs/xfs/linux-2.6/xfs_buf.c79
-rw-r--r--include/asm-frv/pgtable.h2
-rw-r--r--include/drm/drmP.h2
-rw-r--r--include/drm/drm_crtc.h2
-rw-r--r--include/drm/drm_crtc_helper.h10
-rw-r--r--include/linux/bio.h2
-rw-r--r--include/linux/blktrace_api.h1
-rw-r--r--include/linux/device.h2
-rw-r--r--include/linux/dmaengine.h2
-rw-r--r--include/linux/firmware-map.h2
-rw-r--r--include/linux/fs.h24
-rw-r--r--include/linux/jbd2.h3
-rw-r--r--include/linux/kprobes.h22
-rw-r--r--include/linux/kvm.h10
-rw-r--r--include/linux/kvm_host.h1
-rw-r--r--include/linux/mm.h20
-rw-r--r--include/linux/mmiotrace.h78
-rw-r--r--include/linux/mmzone.h2
-rw-r--r--include/linux/pci_ids.h5
-rw-r--r--include/linux/pm.h2
-rw-r--r--include/linux/seq_file.h1
-rw-r--r--include/linux/serial_core.h1
-rw-r--r--include/linux/slab.h1
-rw-r--r--include/linux/spi/spi_bitbang.h7
-rw-r--r--include/linux/timerfd.h16
-rw-r--r--include/linux/vmalloc.h4
-rw-r--r--init/do_mounts.c13
-rw-r--r--init/do_mounts_md.c5
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/cgroup.c2
-rw-r--r--kernel/futex.c53
-rw-r--r--kernel/kexec.c7
-rw-r--r--kernel/posix-cpu-timers.c60
-rw-r--r--kernel/power/Makefile2
-rw-r--r--kernel/power/console.c6
-rw-r--r--kernel/power/disk.c22
-rw-r--r--kernel/power/main.c8
-rw-r--r--kernel/power/swap.c5
-rw-r--r--kernel/power/user.c8
-rw-r--r--kernel/printk.c15
-rw-r--r--kernel/sched.c15
-rw-r--r--kernel/trace/Kconfig25
-rw-r--r--kernel/trace/ftrace.c6
-rw-r--r--kernel/trace/trace_mmiotrace.c14
-rw-r--r--kernel/trace/trace_selftest.c19
-rw-r--r--lib/Kconfig.debug2
-rw-r--r--mm/page-writeback.c13
-rw-r--r--mm/page_alloc.c27
-rw-r--r--mm/page_io.c2
-rw-r--r--mm/swapfile.c4
-rw-r--r--mm/util.c20
-rw-r--r--mm/vmalloc.c10
-rw-r--r--mm/vmscan.c28
-rw-r--r--net/ipv4/cipso_ipv4.c9
-rw-r--r--scripts/bootgraph.pl4
-rw-r--r--scripts/markup_oops.pl161
-rw-r--r--scripts/mod/file2alias.c1
-rwxr-xr-xscripts/package/mkspec8
-rwxr-xr-xscripts/setlocalversion9
-rwxr-xr-xscripts/tags.sh12
-rw-r--r--security/selinux/netlabel.c4
-rw-r--r--sound/core/jack.c2
-rw-r--r--sound/oss/dmasound/dmasound_atari.c16
-rw-r--r--sound/pci/hda/hda_intel.c8
-rw-r--r--sound/pci/oxygen/virtuoso.c17
-rw-r--r--sound/usb/usbaudio.c20
-rw-r--r--sound/usb/usbmidi.c1
-rw-r--r--virt/kvm/iommu.c6
-rw-r--r--virt/kvm/kvm_main.c43
451 files changed, 7430 insertions, 8100 deletions
diff --git a/CREDITS b/CREDITS
index 2b39168c06aa..5e0736722afd 100644
--- a/CREDITS
+++ b/CREDITS
@@ -2166,7 +2166,6 @@ D: Initial implementation of VC's, pty's and select()
N: Pavel Machek
E: pavel@ucw.cz
-E: pavel@suse.cz
D: Softcursor for vga, hypertech cdrom support, vcsa bugfix, nbd
D: sun4/330 port, capabilities for elf, speedup for rm on ext2, USB,
D: work on suspend-to-ram/disk, killing duplicates from ioctl32
diff --git a/Documentation/ABI/testing/sysfs-firmware-memmap b/Documentation/ABI/testing/sysfs-firmware-memmap
index 0d99ee6ae02e..eca0d65087dc 100644
--- a/Documentation/ABI/testing/sysfs-firmware-memmap
+++ b/Documentation/ABI/testing/sysfs-firmware-memmap
@@ -1,6 +1,6 @@
What: /sys/firmware/memmap/
Date: June 2008
-Contact: Bernhard Walle <bwalle@suse.de>
+Contact: Bernhard Walle <bernhard.walle@gmx.de>
Description:
On all platforms, the firmware provides a memory map which the
kernel reads. The resources from that memory map are registered
diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile
index dc3154e49279..1462ed86d40a 100644
--- a/Documentation/DocBook/Makefile
+++ b/Documentation/DocBook/Makefile
@@ -6,7 +6,7 @@
# To add a new book the only step required is to add the book to the
# list of DOCBOOKS.
-DOCBOOKS := z8530book.xml mcabook.xml \
+DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
procfs-guide.xml writing_usb_driver.xml networking.xml \
kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl
new file mode 100644
index 000000000000..94a20fe8fedf
--- /dev/null
+++ b/Documentation/DocBook/device-drivers.tmpl
@@ -0,0 +1,418 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
+
+<book id="LinuxDriversAPI">
+ <bookinfo>
+ <title>Linux Device Drivers</title>
+
+ <legalnotice>
+ <para>
+ This documentation 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.
+ </para>
+
+ <para>
+ 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.
+ </para>
+
+ <para>
+ 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
+ </para>
+
+ <para>
+ For more details see the file COPYING in the source
+ distribution of Linux.
+ </para>
+ </legalnotice>
+ </bookinfo>
+
+<toc></toc>
+
+ <chapter id="Basics">
+ <title>Driver Basics</title>
+ <sect1><title>Driver Entry and Exit points</title>
+!Iinclude/linux/init.h
+ </sect1>
+
+ <sect1><title>Atomic and pointer manipulation</title>
+!Iarch/x86/include/asm/atomic_32.h
+!Iarch/x86/include/asm/unaligned.h
+ </sect1>
+
+ <sect1><title>Delaying, scheduling, and timer routines</title>
+!Iinclude/linux/sched.h
+!Ekernel/sched.c
+!Ekernel/timer.c
+ </sect1>
+ <sect1><title>High-resolution timers</title>
+!Iinclude/linux/ktime.h
+!Iinclude/linux/hrtimer.h
+!Ekernel/hrtimer.c
+ </sect1>
+ <sect1><title>Workqueues and Kevents</title>
+!Ekernel/workqueue.c
+ </sect1>
+ <sect1><title>Internal Functions</title>
+!Ikernel/exit.c
+!Ikernel/signal.c
+!Iinclude/linux/kthread.h
+!Ekernel/kthread.c
+ </sect1>
+
+ <sect1><title>Kernel objects manipulation</title>
+<!--
+X!Iinclude/linux/kobject.h
+-->
+!Elib/kobject.c
+ </sect1>
+
+ <sect1><title>Kernel utility functions</title>
+!Iinclude/linux/kernel.h
+!Ekernel/printk.c
+!Ekernel/panic.c
+!Ekernel/sys.c
+!Ekernel/rcupdate.c
+ </sect1>
+
+ <sect1><title>Device Resource Management</title>
+!Edrivers/base/devres.c
+ </sect1>
+
+ </chapter>
+
+ <chapter id="devdrivers">
+ <title>Device drivers infrastructure</title>
+ <sect1><title>Device Drivers Base</title>
+<!--
+X!Iinclude/linux/device.h
+-->
+!Edrivers/base/driver.c
+!Edrivers/base/core.c
+!Edrivers/base/class.c
+!Edrivers/base/firmware_class.c
+!Edrivers/base/transport_class.c
+<!-- Cannot be included, because
+ attribute_container_add_class_device_adapter
+ and attribute_container_classdev_to_container
+ exceed allowed 44 characters maximum
+X!Edrivers/base/attribute_container.c
+-->
+!Edrivers/base/sys.c
+<!--
+X!Edrivers/base/interface.c
+-->
+!Edrivers/base/platform.c
+!Edrivers/base/bus.c
+ </sect1>
+ <sect1><title>Device Drivers Power Management</title>
+!Edrivers/base/power/main.c
+ </sect1>
+ <sect1><title>Device Drivers ACPI Support</title>
+<!-- Internal functions only
+X!Edrivers/acpi/sleep/main.c
+X!Edrivers/acpi/sleep/wakeup.c
+X!Edrivers/acpi/motherboard.c
+X!Edrivers/acpi/bus.c
+-->
+!Edrivers/acpi/scan.c
+!Idrivers/acpi/scan.c
+<!-- No correct structured comments
+X!Edrivers/acpi/pci_bind.c
+-->
+ </sect1>
+ <sect1><title>Device drivers PnP support</title>
+!Idrivers/pnp/core.c
+<!-- No correct structured comments
+X!Edrivers/pnp/system.c
+ -->
+!Edrivers/pnp/card.c
+!Idrivers/pnp/driver.c
+!Edrivers/pnp/manager.c
+!Edrivers/pnp/support.c
+ </sect1>
+ <sect1><title>Userspace IO devices</title>
+!Edrivers/uio/uio.c
+!Iinclude/linux/uio_driver.h
+ </sect1>
+ </chapter>
+
+ <chapter id="parportdev">
+ <title>Parallel Port Devices</title>
+!Iinclude/linux/parport.h
+!Edrivers/parport/ieee1284.c
+!Edrivers/parport/share.c
+!Idrivers/parport/daisy.c
+ </chapter>
+
+ <chapter id="message_devices">
+ <title>Message-based devices</title>
+ <sect1><title>Fusion message devices</title>
+!Edrivers/message/fusion/mptbase.c
+!Idrivers/message/fusion/mptbase.c
+!Edrivers/message/fusion/mptscsih.c
+!Idrivers/message/fusion/mptscsih.c
+!Idrivers/message/fusion/mptctl.c
+!Idrivers/message/fusion/mptspi.c
+!Idrivers/message/fusion/mptfc.c
+!Idrivers/message/fusion/mptlan.c
+ </sect1>
+ <sect1><title>I2O message devices</title>
+!Iinclude/linux/i2o.h
+!Idrivers/message/i2o/core.h
+!Edrivers/message/i2o/iop.c
+!Idrivers/message/i2o/iop.c
+!Idrivers/message/i2o/config-osm.c
+!Edrivers/message/i2o/exec-osm.c
+!Idrivers/message/i2o/exec-osm.c
+!Idrivers/message/i2o/bus-osm.c
+!Edrivers/message/i2o/device.c
+!Idrivers/message/i2o/device.c
+!Idrivers/message/i2o/driver.c
+!Idrivers/message/i2o/pci.c
+!Idrivers/message/i2o/i2o_block.c
+!Idrivers/message/i2o/i2o_scsi.c
+!Idrivers/message/i2o/i2o_proc.c
+ </sect1>
+ </chapter>
+
+ <chapter id="snddev">
+ <title>Sound Devices</title>
+!Iinclude/sound/core.h
+!Esound/sound_core.c
+!Iinclude/sound/pcm.h
+!Esound/core/pcm.c
+!Esound/core/device.c
+!Esound/core/info.c
+!Esound/core/rawmidi.c
+!Esound/core/sound.c
+!Esound/core/memory.c
+!Esound/core/pcm_memory.c
+!Esound/core/init.c
+!Esound/core/isadma.c
+!Esound/core/control.c
+!Esound/core/pcm_lib.c
+!Esound/core/hwdep.c
+!Esound/core/pcm_native.c
+!Esound/core/memalloc.c
+<!-- FIXME: Removed for now since no structured comments in source
+X!Isound/sound_firmware.c
+-->
+ </chapter>
+
+ <chapter id="uart16x50">
+ <title>16x50 UART Driver</title>
+!Iinclude/linux/serial_core.h
+!Edrivers/serial/serial_core.c
+!Edrivers/serial/8250.c
+ </chapter>
+
+ <chapter id="fbdev">
+ <title>Frame Buffer Library</title>
+
+ <para>
+ The frame buffer drivers depend heavily on four data structures.
+ These structures are declared in include/linux/fb.h. They are
+ fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs.
+ The last three can be made available to and from userland.
+ </para>
+
+ <para>
+ fb_info defines the current state of a particular video card.
+ Inside fb_info, there exists a fb_ops structure which is a
+ collection of needed functions to make fbdev and fbcon work.
+ fb_info is only visible to the kernel.
+ </para>
+
+ <para>
+ fb_var_screeninfo is used to describe the features of a video card
+ that are user defined. With fb_var_screeninfo, things such as
+ depth and the resolution may be defined.
+ </para>
+
+ <para>
+ The next structure is fb_fix_screeninfo. This defines the
+ properties of a card that are created when a mode is set and can't
+ be changed otherwise. A good example of this is the start of the
+ frame buffer memory. This "locks" the address of the frame buffer
+ memory, so that it cannot be changed or moved.
+ </para>
+
+ <para>
+ The last structure is fb_monospecs. In the old API, there was
+ little importance for fb_monospecs. This allowed for forbidden things
+ such as setting a mode of 800x600 on a fix frequency monitor. With
+ the new API, fb_monospecs prevents such things, and if used
+ correctly, can prevent a monitor from being cooked. fb_monospecs
+ will not be useful until kernels 2.5.x.
+ </para>
+
+ <sect1><title>Frame Buffer Memory</title>
+!Edrivers/video/fbmem.c
+ </sect1>
+<!--
+ <sect1><title>Frame Buffer Console</title>
+X!Edrivers/video/console/fbcon.c
+ </sect1>
+-->
+ <sect1><title>Frame Buffer Colormap</title>
+!Edrivers/video/fbcmap.c
+ </sect1>
+<!-- FIXME:
+ drivers/video/fbgen.c has no docs, which stuffs up the sgml. Comment
+ out until somebody adds docs. KAO
+ <sect1><title>Frame Buffer Generic Functions</title>
+X!Idrivers/video/fbgen.c
+ </sect1>
+KAO -->
+ <sect1><title>Frame Buffer Video Mode Database</title>
+!Idrivers/video/modedb.c
+!Edrivers/video/modedb.c
+ </sect1>
+ <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
+!Edrivers/video/macmodes.c
+ </sect1>
+ <sect1><title>Frame Buffer Fonts</title>
+ <para>
+ Refer to the file drivers/video/console/fonts.c for more information.
+ </para>
+<!-- FIXME: Removed for now since no structured comments in source
+X!Idrivers/video/console/fonts.c
+-->
+ </sect1>
+ </chapter>
+
+ <chapter id="input_subsystem">
+ <title>Input Subsystem</title>
+!Iinclude/linux/input.h
+!Edrivers/input/input.c
+!Edrivers/input/ff-core.c
+!Edrivers/input/ff-memless.c
+ </chapter>
+
+ <chapter id="spi">
+ <title>Serial Peripheral Interface (SPI)</title>
+ <para>
+ SPI is the "Serial Peripheral Interface", widely used with
+ embedded systems because it is a simple and efficient
+ interface: basically a multiplexed shift register.
+ Its three signal wires hold a clock (SCK, often in the range
+ of 1-20 MHz), a "Master Out, Slave In" (MOSI) data line, and
+ a "Master In, Slave Out" (MISO) data line.
+ SPI is a full duplex protocol; for each bit shifted out the
+ MOSI line (one per clock) another is shifted in on the MISO line.
+ Those bits are assembled into words of various sizes on the
+ way to and from system memory.
+ An additional chipselect line is usually active-low (nCS);
+ four signals are normally used for each peripheral, plus
+ sometimes an interrupt.
+ </para>
+ <para>
+ The SPI bus facilities listed here provide a generalized
+ interface to declare SPI busses and devices, manage them
+ according to the standard Linux driver model, and perform
+ input/output operations.
+ At this time, only "master" side interfaces are supported,
+ where Linux talks to SPI peripherals and does not implement
+ such a peripheral itself.
+ (Interfaces to support implementing SPI slaves would
+ necessarily look different.)
+ </para>
+ <para>
+ The programming interface is structured around two kinds of driver,
+ and two kinds of device.
+ A "Controller Driver" abstracts the controller hardware, which may
+ be as simple as a set of GPIO pins or as complex as a pair of FIFOs
+ connected to dual DMA engines on the other side of the SPI shift
+ register (maximizing throughput). Such drivers bridge between
+ whatever bus they sit on (often the platform bus) and SPI, and
+ expose the SPI side of their device as a
+ <structname>struct spi_master</structname>.
+ SPI devices are children of that master, represented as a
+ <structname>struct spi_device</structname> and manufactured from
+ <structname>struct spi_board_info</structname> descriptors which
+ are usually provided by board-specific initialization code.
+ A <structname>struct spi_driver</structname> is called a
+ "Protocol Driver", and is bound to a spi_device using normal
+ driver model calls.
+ </para>
+ <para>
+ The I/O model is a set of queued messages. Protocol drivers
+ submit one or more <structname>struct spi_message</structname>
+ objects, which are processed and completed asynchronously.
+ (There are synchronous wrappers, however.) Messages are
+ built from one or more <structname>struct spi_transfer</structname>
+ objects, each of which wraps a full duplex SPI transfer.
+ A variety of protocol tweaking options are needed, because
+ different chips adopt very different policies for how they
+ use the bits transferred with SPI.
+ </para>
+!Iinclude/linux/spi/spi.h
+!Fdrivers/spi/spi.c spi_register_board_info
+!Edrivers/spi/spi.c
+ </chapter>
+
+ <chapter id="i2c">
+ <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
+
+ <para>
+ I<superscript>2</superscript>C (or without fancy typography, "I2C")
+ is an acronym for the "Inter-IC" bus, a simple bus protocol which is
+ widely used where low data rate communications suffice.
+ Since it's also a licensed trademark, some vendors use another
+ name (such as "Two-Wire Interface", TWI) for the same bus.
+ I2C only needs two signals (SCL for clock, SDA for data), conserving
+ board real estate and minimizing signal quality issues.
+ Most I2C devices use seven bit addresses, and bus speeds of up
+ to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
+ found wide use.
+ I2C is a multi-master bus; open drain signaling is used to
+ arbitrate between masters, as well as to handshake and to
+ synchronize clocks from slower clients.
+ </para>
+
+ <para>
+ The Linux I2C programming interfaces support only the master
+ side of bus interactions, not the slave side.
+ The programming interface is structured around two kinds of driver,
+ and two kinds of device.
+ An I2C "Adapter Driver" abstracts the controller hardware; it binds
+ to a physical device (perhaps a PCI device or platform_device) and
+ exposes a <structname>struct i2c_adapter</structname> representing
+ each I2C bus segment it manages.
+ On each I2C bus segment will be I2C devices represented by a
+ <structname>struct i2c_client</structname>. Those devices will
+ be bound to a <structname>struct i2c_driver</structname>,
+ which should follow the standard Linux driver model.
+ (At this writing, a legacy model is more widely used.)
+ There are functions to perform various I2C protocol operations; at
+ this writing all such functions are usable only from task context.
+ </para>
+
+ <para>
+ The System Management Bus (SMBus) is a sibling protocol. Most SMBus
+ systems are also I2C conformant. The electrical constraints are
+ tighter for SMBus, and it standardizes particular protocol messages
+ and idioms. Controllers that support I2C can also support most
+ SMBus operations, but SMBus controllers don't support all the protocol
+ options that an I2C controller will.
+ There are functions to perform various SMBus protocol operations,
+ either using I2C primitives or by issuing SMBus commands to
+ i2c_adapter devices which don't support those I2C operations.
+ </para>
+
+!Iinclude/linux/i2c.h
+!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
+!Edrivers/i2c/i2c-core.c
+ </chapter>
+
+</book>
diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl
index 5818ff75786a..bc962cda6504 100644
--- a/Documentation/DocBook/kernel-api.tmpl
+++ b/Documentation/DocBook/kernel-api.tmpl
@@ -38,58 +38,6 @@
<toc></toc>
- <chapter id="Basics">
- <title>Driver Basics</title>
- <sect1><title>Driver Entry and Exit points</title>
-!Iinclude/linux/init.h
- </sect1>
-
- <sect1><title>Atomic and pointer manipulation</title>
-!Iarch/x86/include/asm/atomic_32.h
-!Iarch/x86/include/asm/unaligned.h
- </sect1>
-
- <sect1><title>Delaying, scheduling, and timer routines</title>
-!Iinclude/linux/sched.h
-!Ekernel/sched.c
-!Ekernel/timer.c
- </sect1>
- <sect1><title>High-resolution timers</title>
-!Iinclude/linux/ktime.h
-!Iinclude/linux/hrtimer.h
-!Ekernel/hrtimer.c
- </sect1>
- <sect1><title>Workqueues and Kevents</title>
-!Ekernel/workqueue.c
- </sect1>
- <sect1><title>Internal Functions</title>
-!Ikernel/exit.c
-!Ikernel/signal.c
-!Iinclude/linux/kthread.h
-!Ekernel/kthread.c
- </sect1>
-
- <sect1><title>Kernel objects manipulation</title>
-<!--
-X!Iinclude/linux/kobject.h
--->
-!Elib/kobject.c
- </sect1>
-
- <sect1><title>Kernel utility functions</title>
-!Iinclude/linux/kernel.h
-!Ekernel/printk.c
-!Ekernel/panic.c
-!Ekernel/sys.c
-!Ekernel/rcupdate.c
- </sect1>
-
- <sect1><title>Device Resource Management</title>
-!Edrivers/base/devres.c
- </sect1>
-
- </chapter>
-
<chapter id="adt">
<title>Data Types</title>
<sect1><title>Doubly Linked Lists</title>
@@ -298,62 +246,6 @@ X!Earch/x86/kernel/mca_32.c
!Ikernel/acct.c
</chapter>
- <chapter id="devdrivers">
- <title>Device drivers infrastructure</title>
- <sect1><title>Device Drivers Base</title>
-<!--
-X!Iinclude/linux/device.h
--->
-!Edrivers/base/driver.c
-!Edrivers/base/core.c
-!Edrivers/base/class.c
-!Edrivers/base/firmware_class.c
-!Edrivers/base/transport_class.c
-<!-- Cannot be included, because
- attribute_container_add_class_device_adapter
- and attribute_container_classdev_to_container
- exceed allowed 44 characters maximum
-X!Edrivers/base/attribute_container.c
--->
-!Edrivers/base/sys.c
-<!--
-X!Edrivers/base/interface.c
--->
-!Edrivers/base/platform.c
-!Edrivers/base/bus.c
- </sect1>
- <sect1><title>Device Drivers Power Management</title>
-!Edrivers/base/power/main.c
- </sect1>
- <sect1><title>Device Drivers ACPI Support</title>
-<!-- Internal functions only
-X!Edrivers/acpi/sleep/main.c
-X!Edrivers/acpi/sleep/wakeup.c
-X!Edrivers/acpi/motherboard.c
-X!Edrivers/acpi/bus.c
--->
-!Edrivers/acpi/scan.c
-!Idrivers/acpi/scan.c
-<!-- No correct structured comments
-X!Edrivers/acpi/pci_bind.c
--->
- </sect1>
- <sect1><title>Device drivers PnP support</title>
-!Idrivers/pnp/core.c
-<!-- No correct structured comments
-X!Edrivers/pnp/system.c
- -->
-!Edrivers/pnp/card.c
-!Idrivers/pnp/driver.c
-!Edrivers/pnp/manager.c
-!Edrivers/pnp/support.c
- </sect1>
- <sect1><title>Userspace IO devices</title>
-!Edrivers/uio/uio.c
-!Iinclude/linux/uio_driver.h
- </sect1>
- </chapter>
-
<chapter id="blkdev">
<title>Block Devices</title>
!Eblock/blk-core.c
@@ -381,275 +273,6 @@ X!Edrivers/pnp/system.c
!Edrivers/char/misc.c
</chapter>
- <chapter id="parportdev">
- <title>Parallel Port Devices</title>
-!Iinclude/linux/parport.h
-!Edrivers/parport/ieee1284.c
-!Edrivers/parport/share.c
-!Idrivers/parport/daisy.c
- </chapter>
-
- <chapter id="message_devices">
- <title>Message-based devices</title>
- <sect1><title>Fusion message devices</title>
-!Edrivers/message/fusion/mptbase.c
-!Idrivers/message/fusion/mptbase.c
-!Edrivers/message/fusion/mptscsih.c
-!Idrivers/message/fusion/mptscsih.c
-!Idrivers/message/fusion/mptctl.c
-!Idrivers/message/fusion/mptspi.c
-!Idrivers/message/fusion/mptfc.c
-!Idrivers/message/fusion/mptlan.c
- </sect1>
- <sect1><title>I2O message devices</title>
-!Iinclude/linux/i2o.h
-!Idrivers/message/i2o/core.h
-!Edrivers/message/i2o/iop.c
-!Idrivers/message/i2o/iop.c
-!Idrivers/message/i2o/config-osm.c
-!Edrivers/message/i2o/exec-osm.c
-!Idrivers/message/i2o/exec-osm.c
-!Idrivers/message/i2o/bus-osm.c
-!Edrivers/message/i2o/device.c
-!Idrivers/message/i2o/device.c
-!Idrivers/message/i2o/driver.c
-!Idrivers/message/i2o/pci.c
-!Idrivers/message/i2o/i2o_block.c
-!Idrivers/message/i2o/i2o_scsi.c
-!Idrivers/message/i2o/i2o_proc.c
- </sect1>
- </chapter>
-
- <chapter id="snddev">
- <title>Sound Devices</title>
-!Iinclude/sound/core.h
-!Esound/sound_core.c
-!Iinclude/sound/pcm.h
-!Esound/core/pcm.c
-!Esound/core/device.c
-!Esound/core/info.c
-!Esound/core/rawmidi.c
-!Esound/core/sound.c
-!Esound/core/memory.c
-!Esound/core/pcm_memory.c
-!Esound/core/init.c
-!Esound/core/isadma.c
-!Esound/core/control.c
-!Esound/core/pcm_lib.c
-!Esound/core/hwdep.c
-!Esound/core/pcm_native.c
-!Esound/core/memalloc.c
-<!-- FIXME: Removed for now since no structured comments in source
-X!Isound/sound_firmware.c
--->
- </chapter>
-
- <chapter id="uart16x50">
- <title>16x50 UART Driver</title>
-!Iinclude/linux/serial_core.h
-!Edrivers/serial/serial_core.c
-!Edrivers/serial/8250.c
- </chapter>
-
- <chapter id="fbdev">
- <title>Frame Buffer Library</title>
-
- <para>
- The frame buffer drivers depend heavily on four data structures.
- These structures are declared in include/linux/fb.h. They are
- fb_info, fb_var_screeninfo, fb_fix_screeninfo and fb_monospecs.
- The last three can be made available to and from userland.
- </para>
-
- <para>
- fb_info defines the current state of a particular video card.
- Inside fb_info, there exists a fb_ops structure which is a
- collection of needed functions to make fbdev and fbcon work.
- fb_info is only visible to the kernel.
- </para>
-
- <para>
- fb_var_screeninfo is used to describe the features of a video card
- that are user defined. With fb_var_screeninfo, things such as
- depth and the resolution may be defined.
- </para>
-
- <para>
- The next structure is fb_fix_screeninfo. This defines the
- properties of a card that are created when a mode is set and can't
- be changed otherwise. A good example of this is the start of the
- frame buffer memory. This "locks" the address of the frame buffer
- memory, so that it cannot be changed or moved.
- </para>
-
- <para>
- The last structure is fb_monospecs. In the old API, there was
- little importance for fb_monospecs. This allowed for forbidden things
- such as setting a mode of 800x600 on a fix frequency monitor. With
- the new API, fb_monospecs prevents such things, and if used
- correctly, can prevent a monitor from being cooked. fb_monospecs
- will not be useful until kernels 2.5.x.
- </para>
-
- <sect1><title>Frame Buffer Memory</title>
-!Edrivers/video/fbmem.c
- </sect1>
-<!--
- <sect1><title>Frame Buffer Console</title>
-X!Edrivers/video/console/fbcon.c
- </sect1>
--->
- <sect1><title>Frame Buffer Colormap</title>
-!Edrivers/video/fbcmap.c
- </sect1>
-<!-- FIXME:
- drivers/video/fbgen.c has no docs, which stuffs up the sgml. Comment
- out until somebody adds docs. KAO
- <sect1><title>Frame Buffer Generic Functions</title>
-X!Idrivers/video/fbgen.c
- </sect1>
-KAO -->
- <sect1><title>Frame Buffer Video Mode Database</title>
-!Idrivers/video/modedb.c
-!Edrivers/video/modedb.c
- </sect1>
- <sect1><title>Frame Buffer Macintosh Video Mode Database</title>
-!Edrivers/video/macmodes.c
- </sect1>
- <sect1><title>Frame Buffer Fonts</title>
- <para>
- Refer to the file drivers/video/console/fonts.c for more information.
- </para>
-<!-- FIXME: Removed for now since no structured comments in source
-X!Idrivers/video/console/fonts.c
--->
- </sect1>
- </chapter>
-
- <chapter id="input_subsystem">
- <title>Input Subsystem</title>
-!Iinclude/linux/input.h
-!Edrivers/input/input.c
-!Edrivers/input/ff-core.c
-!Edrivers/input/ff-memless.c
- </chapter>
-
- <chapter id="spi">
- <title>Serial Peripheral Interface (SPI)</title>
- <para>
- SPI is the "Serial Peripheral Interface", widely used with
- embedded systems because it is a simple and efficient
- interface: basically a multiplexed shift register.
- Its three signal wires hold a clock (SCK, often in the range
- of 1-20 MHz), a "Master Out, Slave In" (MOSI) data line, and
- a "Master In, Slave Out" (MISO) data line.
- SPI is a full duplex protocol; for each bit shifted out the
- MOSI line (one per clock) another is shifted in on the MISO line.
- Those bits are assembled into words of various sizes on the
- way to and from system memory.
- An additional chipselect line is usually active-low (nCS);
- four signals are normally used for each peripheral, plus
- sometimes an interrupt.
- </para>
- <para>
- The SPI bus facilities listed here provide a generalized
- interface to declare SPI busses and devices, manage them
- according to the standard Linux driver model, and perform
- input/output operations.
- At this time, only "master" side interfaces are supported,
- where Linux talks to SPI peripherals and does not implement
- such a peripheral itself.
- (Interfaces to support implementing SPI slaves would
- necessarily look different.)
- </para>
- <para>
- The programming interface is structured around two kinds of driver,
- and two kinds of device.
- A "Controller Driver" abstracts the controller hardware, which may
- be as simple as a set of GPIO pins or as complex as a pair of FIFOs
- connected to dual DMA engines on the other side of the SPI shift
- register (maximizing throughput). Such drivers bridge between
- whatever bus they sit on (often the platform bus) and SPI, and
- expose the SPI side of their device as a
- <structname>struct spi_master</structname>.
- SPI devices are children of that master, represented as a
- <structname>struct spi_device</structname> and manufactured from
- <structname>struct spi_board_info</structname> descriptors which
- are usually provided by board-specific initialization code.
- A <structname>struct spi_driver</structname> is called a
- "Protocol Driver", and is bound to a spi_device using normal
- driver model calls.
- </para>
- <para>
- The I/O model is a set of queued messages. Protocol drivers
- submit one or more <structname>struct spi_message</structname>
- objects, which are processed and completed asynchronously.
- (There are synchronous wrappers, however.) Messages are
- built from one or more <structname>struct spi_transfer</structname>
- objects, each of which wraps a full duplex SPI transfer.
- A variety of protocol tweaking options are needed, because
- different chips adopt very different policies for how they
- use the bits transferred with SPI.
- </para>
-!Iinclude/linux/spi/spi.h
-!Fdrivers/spi/spi.c spi_register_board_info
-!Edrivers/spi/spi.c
- </chapter>
-
- <chapter id="i2c">
- <title>I<superscript>2</superscript>C and SMBus Subsystem</title>
-
- <para>
- I<superscript>2</superscript>C (or without fancy typography, "I2C")
- is an acronym for the "Inter-IC" bus, a simple bus protocol which is
- widely used where low data rate communications suffice.
- Since it's also a licensed trademark, some vendors use another
- name (such as "Two-Wire Interface", TWI) for the same bus.
- I2C only needs two signals (SCL for clock, SDA for data), conserving
- board real estate and minimizing signal quality issues.
- Most I2C devices use seven bit addresses, and bus speeds of up
- to 400 kHz; there's a high speed extension (3.4 MHz) that's not yet
- found wide use.
- I2C is a multi-master bus; open drain signaling is used to
- arbitrate between masters, as well as to handshake and to
- synchronize clocks from slower clients.
- </para>
-
- <para>
- The Linux I2C programming interfaces support only the master
- side of bus interactions, not the slave side.
- The programming interface is structured around two kinds of driver,
- and two kinds of device.
- An I2C "Adapter Driver" abstracts the controller hardware; it binds
- to a physical device (perhaps a PCI device or platform_device) and
- exposes a <structname>struct i2c_adapter</structname> representing
- each I2C bus segment it manages.
- On each I2C bus segment will be I2C devices represented by a
- <structname>struct i2c_client</structname>. Those devices will
- be bound to a <structname>struct i2c_driver</structname>,
- which should follow the standard Linux driver model.
- (At this writing, a legacy model is more widely used.)
- There are functions to perform various I2C protocol operations; at
- this writing all such functions are usable only from task context.
- </para>
-
- <para>
- The System Management Bus (SMBus) is a sibling protocol. Most SMBus
- systems are also I2C conformant. The electrical constraints are
- tighter for SMBus, and it standardizes particular protocol messages
- and idioms. Controllers that support I2C can also support most
- SMBus operations, but SMBus controllers don't support all the protocol
- options that an I2C controller will.
- There are functions to perform various SMBus protocol operations,
- either using I2C primitives or by issuing SMBus commands to
- i2c_adapter devices which don't support those I2C operations.
- </para>
-
-!Iinclude/linux/i2c.h
-!Fdrivers/i2c/i2c-boardinfo.c i2c_register_board_info
-!Edrivers/i2c/i2c-core.c
- </chapter>
-
<chapter id="clk">
<title>Clock Framework</title>
diff --git a/Documentation/PCI/PCIEBUS-HOWTO.txt b/Documentation/PCI/PCIEBUS-HOWTO.txt
index 9a07e38631b0..6bd5f372adec 100644
--- a/Documentation/PCI/PCIEBUS-HOWTO.txt
+++ b/Documentation/PCI/PCIEBUS-HOWTO.txt
@@ -93,7 +93,7 @@ the PCI Express Port Bus driver from loading a service driver.
int pcie_port_service_register(struct pcie_port_service_driver *new)
-This API replaces the Linux Driver Model's pci_module_init API. A
+This API replaces the Linux Driver Model's pci_register_driver API. A
service driver should always calls pcie_port_service_register at
module init. Note that after service driver being loaded, calls
such as pci_enable_device(dev) and pci_set_master(dev) are no longer
diff --git a/Documentation/cgroups/cgroups.txt b/Documentation/cgroups/cgroups.txt
index d9e5d6f41b92..93feb8444489 100644
--- a/Documentation/cgroups/cgroups.txt
+++ b/Documentation/cgroups/cgroups.txt
@@ -252,10 +252,8 @@ cgroup file system directories.
When a task is moved from one cgroup to another, it gets a new
css_set pointer - if there's an already existing css_set with the
desired collection of cgroups then that group is reused, else a new
-css_set is allocated. Note that the current implementation uses a
-linear search to locate an appropriate existing css_set, so isn't
-very efficient. A future version will use a hash table for better
-performance.
+css_set is allocated. The appropriate existing css_set is located by
+looking into a hash table.
To allow access from a cgroup to the css_sets (and hence tasks)
that comprise it, a set of cg_cgroup_link objects form a lattice;
diff --git a/Documentation/cgroups/cpusets.txt b/Documentation/cgroups/cpusets.txt
index 5c86c258c791..0611e9528c7c 100644
--- a/Documentation/cgroups/cpusets.txt
+++ b/Documentation/cgroups/cpusets.txt
@@ -142,7 +142,7 @@ into the rest of the kernel, none in performance critical paths:
- in fork and exit, to attach and detach a task from its cpuset.
- in sched_setaffinity, to mask the requested CPUs by what's
allowed in that tasks cpuset.
- - in sched.c migrate_all_tasks(), to keep migrating tasks within
+ - in sched.c migrate_live_tasks(), to keep migrating tasks within
the CPUs allowed by their cpuset, if possible.
- in the mbind and set_mempolicy system calls, to mask the requested
Memory Nodes by what's allowed in that tasks cpuset.
@@ -175,6 +175,10 @@ files describing that cpuset:
- mem_exclusive flag: is memory placement exclusive?
- mem_hardwall flag: is memory allocation hardwalled
- memory_pressure: measure of how much paging pressure in cpuset
+ - memory_spread_page flag: if set, spread page cache evenly on allowed nodes
+ - memory_spread_slab flag: if set, spread slab cache evenly on allowed nodes
+ - sched_load_balance flag: if set, load balance within CPUs on that cpuset
+ - sched_relax_domain_level: the searching range when migrating tasks
In addition, the root cpuset only has the following file:
- memory_pressure_enabled flag: compute memory_pressure?
@@ -252,7 +256,7 @@ is causing.
This is useful both on tightly managed systems running a wide mix of
submitted jobs, which may choose to terminate or re-prioritize jobs that
-are trying to use more memory than allowed on the nodes assigned them,
+are trying to use more memory than allowed on the nodes assigned to them,
and with tightly coupled, long running, massively parallel scientific
computing jobs that will dramatically fail to meet required performance
goals if they start to use more memory than allowed to them.
@@ -378,7 +382,7 @@ as cpusets and sched_setaffinity.
The algorithmic cost of load balancing and its impact on key shared
kernel data structures such as the task list increases more than
linearly with the number of CPUs being balanced. So the scheduler
-has support to partition the systems CPUs into a number of sched
+has support to partition the systems CPUs into a number of sched
domains such that it only load balances within each sched domain.
Each sched domain covers some subset of the CPUs in the system;
no two sched domains overlap; some CPUs might not be in any sched
@@ -485,17 +489,22 @@ of CPUs allowed to a cpuset having 'sched_load_balance' enabled.
The internal kernel cpuset to scheduler interface passes from the
cpuset code to the scheduler code a partition of the load balanced
CPUs in the system. This partition is a set of subsets (represented
-as an array of cpumask_t) of CPUs, pairwise disjoint, that cover all
-the CPUs that must be load balanced.
-
-Whenever the 'sched_load_balance' flag changes, or CPUs come or go
-from a cpuset with this flag enabled, or a cpuset with this flag
-enabled is removed, the cpuset code builds a new such partition and
-passes it to the scheduler sched domain setup code, to have the sched
-domains rebuilt as necessary.
+as an array of struct cpumask) of CPUs, pairwise disjoint, that cover
+all the CPUs that must be load balanced.
+
+The cpuset code builds a new such partition and passes it to the
+scheduler sched domain setup code, to have the sched domains rebuilt
+as necessary, whenever:
+ - the 'sched_load_balance' flag of a cpuset with non-empty CPUs changes,
+ - or CPUs come or go from a cpuset with this flag enabled,
+ - or 'sched_relax_domain_level' value of a cpuset with non-empty CPUs
+ and with this flag enabled changes,
+ - or a cpuset with non-empty CPUs and with this flag enabled is removed,
+ - or a cpu is offlined/onlined.
This partition exactly defines what sched domains the scheduler should
-setup - one sched domain for each element (cpumask_t) in the partition.
+setup - one sched domain for each element (struct cpumask) in the
+partition.
The scheduler remembers the currently active sched domain partitions.
When the scheduler routine partition_sched_domains() is invoked from
@@ -559,7 +568,7 @@ domain, the largest value among those is used. Be careful, if one
requests 0 and others are -1 then 0 is used.
Note that modifying this file will have both good and bad effects,
-and whether it is acceptable or not will be depend on your situation.
+and whether it is acceptable or not depends on your situation.
Don't modify this file if you are not sure.
If your situation is:
@@ -600,19 +609,15 @@ to allocate a page of memory for that task.
If a cpuset has its 'cpus' modified, then each task in that cpuset
will have its allowed CPU placement changed immediately. Similarly,
-if a tasks pid is written to a cpusets 'tasks' file, in either its
-current cpuset or another cpuset, then its allowed CPU placement is
-changed immediately. If such a task had been bound to some subset
-of its cpuset using the sched_setaffinity() call, the task will be
-allowed to run on any CPU allowed in its new cpuset, negating the
-affect of the prior sched_setaffinity() call.
+if a tasks pid is written to another cpusets 'tasks' file, then its
+allowed CPU placement is changed immediately. If such a task had been
+bound to some subset of its cpuset using the sched_setaffinity() call,
+the task will be allowed to run on any CPU allowed in its new cpuset,
+negating the effect of the prior sched_setaffinity() call.
In summary, the memory placement of a task whose cpuset is changed is
updated by the kernel, on the next allocation of a page for that task,
-but the processor placement is not updated, until that tasks pid is
-rewritten to the 'tasks' file of its cpuset. This is done to avoid
-impacting the scheduler code in the kernel with a check for changes
-in a tasks processor placement.
+and the processor placement is updated immediately.
Normally, once a page is allocated (given a physical page
of main memory) then that page stays on whatever node it
@@ -681,10 +686,14 @@ and then start a subshell 'sh' in that cpuset:
# The next line should display '/Charlie'
cat /proc/self/cpuset
-In the future, a C library interface to cpusets will likely be
-available. For now, the only way to query or modify cpusets is
-via the cpuset file system, using the various cd, mkdir, echo, cat,
-rmdir commands from the shell, or their equivalent from C.
+There are ways to query or modify cpusets:
+ - via the cpuset file system directly, using the various cd, mkdir, echo,
+ cat, rmdir commands from the shell, or their equivalent from C.
+ - via the C library libcpuset.
+ - via the C library libcgroup.
+ (http://sourceforge.net/proects/libcg/)
+ - via the python application cset.
+ (http://developer.novell.com/wiki/index.php/Cpuset)
The sched_setaffinity calls can also be done at the shell prompt using
SGI's runon or Robert Love's taskset. The mbind and set_mempolicy
@@ -756,7 +765,7 @@ mount -t cpuset X /dev/cpuset
is equivalent to
-mount -t cgroup -ocpuset X /dev/cpuset
+mount -t cgroup -ocpuset,noprefix X /dev/cpuset
echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent
2.2 Adding/removing cpus
diff --git a/Documentation/driver-model/device.txt b/Documentation/driver-model/device.txt
index a05ec50f8004..a7cbfff40d07 100644
--- a/Documentation/driver-model/device.txt
+++ b/Documentation/driver-model/device.txt
@@ -127,9 +127,11 @@ void unlock_device(struct device * dev);
Attributes
~~~~~~~~~~
struct device_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
- ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
+ struct attribute attr;
+ ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
};
Attributes of devices can be exported via drivers using a simple
diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt
index 9e9c348275a9..7e81e37c0b1e 100644
--- a/Documentation/filesystems/sysfs.txt
+++ b/Documentation/filesystems/sysfs.txt
@@ -2,8 +2,10 @@
sysfs - _The_ filesystem for exporting kernel objects.
Patrick Mochel <mochel@osdl.org>
+Mike Murphy <mamurph@cs.clemson.edu>
-10 January 2003
+Revised: 22 February 2009
+Original: 10 January 2003
What it is:
@@ -64,12 +66,13 @@ An attribute definition is simply:
struct attribute {
char * name;
+ struct module *owner;
mode_t mode;
};
-int sysfs_create_file(struct kobject * kobj, struct attribute * attr);
-void sysfs_remove_file(struct kobject * kobj, struct attribute * attr);
+int sysfs_create_file(struct kobject * kobj, const struct attribute * attr);
+void sysfs_remove_file(struct kobject * kobj, const struct attribute * attr);
A bare attribute contains no means to read or write the value of the
@@ -80,9 +83,11 @@ a specific object type.
For example, the driver model defines struct device_attribute like:
struct device_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device * dev, char * buf);
- ssize_t (*store)(struct device * dev, const char * buf);
+ struct attribute attr;
+ ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
};
int device_create_file(struct device *, struct device_attribute *);
@@ -90,12 +95,8 @@ void device_remove_file(struct device *, struct device_attribute *);
It also defines this helper for defining device attributes:
-#define DEVICE_ATTR(_name, _mode, _show, _store) \
-struct device_attribute dev_attr_##_name = { \
- .attr = {.name = __stringify(_name) , .mode = _mode }, \
- .show = _show, \
- .store = _store, \
-};
+#define DEVICE_ATTR(_name, _mode, _show, _store) \
+struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
For example, declaring
@@ -107,9 +108,9 @@ static struct device_attribute dev_attr_foo = {
.attr = {
.name = "foo",
.mode = S_IWUSR | S_IRUGO,
+ .show = show_foo,
+ .store = store_foo,
},
- .show = show_foo,
- .store = store_foo,
};
@@ -161,10 +162,12 @@ To read or write attributes, show() or store() methods must be
specified when declaring the attribute. The method types should be as
simple as those defined for device attributes:
- ssize_t (*show)(struct device * dev, char * buf);
- ssize_t (*store)(struct device * dev, const char * buf);
+ssize_t (*show)(struct device * dev, struct device_attribute * attr,
+ char * buf);
+ssize_t (*store)(struct device * dev, struct device_attribute * attr,
+ const char * buf);
-IOW, they should take only an object and a buffer as parameters.
+IOW, they should take only an object, an attribute, and a buffer as parameters.
sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
@@ -299,14 +302,16 @@ The following interface layers currently exist in sysfs:
Structure:
struct device_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device * dev, char * buf);
- ssize_t (*store)(struct device * dev, const char * buf);
+ struct attribute attr;
+ ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+ char *buf);
+ ssize_t (*store)(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
};
Declaring:
-DEVICE_ATTR(_name, _str, _mode, _show, _store);
+DEVICE_ATTR(_name, _mode, _show, _store);
Creation/Removal:
@@ -342,7 +347,8 @@ Structure:
struct driver_attribute {
struct attribute attr;
ssize_t (*show)(struct device_driver *, char * buf);
- ssize_t (*store)(struct device_driver *, const char * buf);
+ ssize_t (*store)(struct device_driver *, const char * buf,
+ size_t count);
};
Declaring:
diff --git a/Documentation/hwmon/hpfall.c b/Documentation/hwmon/hpfall.c
new file mode 100644
index 000000000000..bbea1ccfd46a
--- /dev/null
+++ b/Documentation/hwmon/hpfall.c
@@ -0,0 +1,101 @@
+/* Disk protection for HP machines.
+ *
+ * Copyright 2008 Eric Piel
+ * Copyright 2009 Pavel Machek <pavel@suse.cz>
+ *
+ * GPLv2.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <signal.h>
+
+void write_int(char *path, int i)
+{
+ char buf[1024];
+ int fd = open(path, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ exit(1);
+ }
+ sprintf(buf, "%d", i);
+ if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+ perror("write");
+ exit(1);
+ }
+ close(fd);
+}
+
+void set_led(int on)
+{
+ write_int("/sys/class/leds/hp::hddprotect/brightness", on);
+}
+
+void protect(int seconds)
+{
+ write_int("/sys/block/sda/device/unload_heads", seconds*1000);
+}
+
+int on_ac(void)
+{
+// /sys/class/power_supply/AC0/online
+}
+
+int lid_open(void)
+{
+// /proc/acpi/button/lid/LID/state
+}
+
+void ignore_me(void)
+{
+ protect(0);
+ set_led(0);
+
+}
+
+int main(int argc, char* argv[])
+{
+ int fd, ret;
+
+ fd = open("/dev/freefall", O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ return EXIT_FAILURE;
+ }
+
+ signal(SIGALRM, ignore_me);
+
+ for (;;) {
+ unsigned char count;
+
+ ret = read(fd, &count, sizeof(count));
+ alarm(0);
+ if ((ret == -1) && (errno == EINTR)) {
+ /* Alarm expired, time to unpark the heads */
+ continue;
+ }
+
+ if (ret != sizeof(count)) {
+ perror("read");
+ break;
+ }
+
+ protect(21);
+ set_led(1);
+ if (1 || on_ac() || lid_open()) {
+ alarm(2);
+ } else {
+ alarm(20);
+ }
+ }
+
+ close(fd);
+ return EXIT_SUCCESS;
+}
diff --git a/Documentation/hwmon/lis3lv02d b/Documentation/hwmon/lis3lv02d
index 0fcfc4a7ccdc..287f8c902656 100644
--- a/Documentation/hwmon/lis3lv02d
+++ b/Documentation/hwmon/lis3lv02d
@@ -33,6 +33,14 @@ rate - reports the sampling rate of the accelerometer device in HZ
This driver also provides an absolute input class device, allowing
the laptop to act as a pinball machine-esque joystick.
+Another feature of the driver is misc device called "freefall" that
+acts similar to /dev/rtc and reacts on free-fall interrupts received
+from the device. It supports blocking operations, poll/select and
+fasync operation modes. You must read 1 bytes from the device. The
+result is number of free-fall interrupts since the last successful
+read (or 255 if number of interrupts would not fit).
+
+
Axes orientation
----------------
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index b182626739ea..f6d5d5b9b2b1 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -114,7 +114,7 @@ In addition, the following text indicates that the option:
Parameters denoted with BOOT are actually interpreted by the boot
loader, and have no meaning to the kernel directly.
Do not modify the syntax of boot loader parameters without extreme
-need or coordination with <Documentation/x86/i386/boot.txt>.
+need or coordination with <Documentation/x86/boot.txt>.
There are also arch-specific kernel-parameters not documented here.
See for example <Documentation/x86/x86_64/boot-options.txt>.
@@ -134,7 +134,7 @@ and is between 256 and 4096 characters. It is defined in the file
acpi= [HW,ACPI,X86-64,i386]
Advanced Configuration and Power Interface
- Format: { force | off | ht | strict | noirq }
+ Format: { force | off | ht | strict | noirq | rsdt }
force -- enable ACPI if default was off
off -- disable ACPI if default was on
noirq -- do not use ACPI for IRQ routing
@@ -2449,7 +2449,7 @@ and is between 256 and 4096 characters. It is defined in the file
See Documentation/fb/modedb.txt.
vga= [BOOT,X86-32] Select a particular video mode
- See Documentation/x86/i386/boot.txt and
+ See Documentation/x86/boot.txt and
Documentation/svga.txt.
Use vga=ask for menu.
This is actually a boot loader parameter; the value is
diff --git a/Documentation/tracers/mmiotrace.txt b/Documentation/tracers/mmiotrace.txt
index cde23b4a12a1..5731c67abc55 100644
--- a/Documentation/tracers/mmiotrace.txt
+++ b/Documentation/tracers/mmiotrace.txt
@@ -78,12 +78,10 @@ to view your kernel log and look for "mmiotrace has lost events" warning. If
events were lost, the trace is incomplete. You should enlarge the buffers and
try again. Buffers are enlarged by first seeing how large the current buffers
are:
-$ cat /debug/tracing/trace_entries
+$ cat /debug/tracing/buffer_size_kb
gives you a number. Approximately double this number and write it back, for
instance:
-$ echo 0 > /debug/tracing/tracing_enabled
-$ echo 128000 > /debug/tracing/trace_entries
-$ echo 1 > /debug/tracing/tracing_enabled
+$ echo 128000 > /debug/tracing/buffer_size_kb
Then start again from the top.
If you are doing a trace for a driver project, e.g. Nouveau, you should also
diff --git a/MAINTAINERS b/MAINTAINERS
index db65b4e6d132..59fd2d1d94a7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -692,6 +692,13 @@ M: kernel@wantstofly.org
L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
S: Maintained
+ARM/NUVOTON W90X900 ARM ARCHITECTURE
+P: Wan ZongShun
+M: mcuos.com@gmail.com
+L: linux-arm-kernel@lists.arm.linux.org.uk (subscribers-only)
+W: http://www.mcuos.com
+S: Maintained
+
ARPD SUPPORT
P: Jonathan Layes
L: netdev@vger.kernel.org
@@ -1905,10 +1912,10 @@ W: http://gigaset307x.sourceforge.net/
S: Maintained
HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
-P: Robert Love
-M: rlove@rlove.org
-M: linux-kernel@vger.kernel.org
-W: http://www.kernel.org/pub/linux/kernel/people/rml/hdaps/
+P: Frank Seidel
+M: frank@f-seidel.de
+L: lm-sensors@lm-sensors.org
+W: http://www.kernel.org/pub/linux/kernel/people/fseidel/hdaps/
S: Maintained
GSPCA FINEPIX SUBDRIVER
@@ -2001,7 +2008,7 @@ S: Maintained
HIBERNATION (aka Software Suspend, aka swsusp)
P: Pavel Machek
-M: pavel@suse.cz
+M: pavel@ucw.cz
P: Rafael J. Wysocki
M: rjw@sisk.pl
L: linux-pm@lists.linux-foundation.org
@@ -3327,8 +3334,8 @@ P: Jeremy Fitzhardinge
M: jeremy@xensource.com
P: Chris Wright
M: chrisw@sous-sol.org
-P: Zachary Amsden
-M: zach@vmware.com
+P: Alok Kataria
+M: akataria@vmware.com
P: Rusty Russell
M: rusty@rustcorp.com.au
L: virtualization@lists.osdl.org
@@ -4172,7 +4179,7 @@ SUSPEND TO RAM
P: Len Brown
M: len.brown@intel.com
P: Pavel Machek
-M: pavel@suse.cz
+M: pavel@ucw.cz
P: Rafael J. Wysocki
M: rjw@sisk.pl
L: linux-pm@lists.linux-foundation.org
@@ -4924,11 +4931,11 @@ L: zd1211-devs@lists.sourceforge.net (subscribers-only)
S: Maintained
ZR36067 VIDEO FOR LINUX DRIVER
-P: Ronald Bultje
-M: rbultje@ronald.bitfreak.net
L: mjpeg-users@lists.sourceforge.net
+L: linux-media@vger.kernel.org
W: http://mjpeg.sourceforge.net/driver-zoran/
-S: Maintained
+T: Mercurial http://linuxtv.org/hg/v4l-dvb
+S: Odd Fixes
ZS DECSTATION Z85C30 SERIAL DRIVER
P: Maciej W. Rozycki
diff --git a/Makefile b/Makefile
index b280cfcf1efe..27fb890a2bff 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 29
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc6
NAME = Erotic Pickled Herring
# *DOCUMENTATION*
@@ -389,6 +389,7 @@ PHONY += outputmakefile
# output directory.
outputmakefile:
ifneq ($(KBUILD_SRC),)
+ $(Q)ln -fsn $(srctree) source
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
@@ -947,7 +948,6 @@ ifneq ($(KBUILD_SRC),)
mkdir -p include2; \
ln -fsn $(srctree)/include/asm-$(SRCARCH) include2/asm; \
fi
- ln -fsn $(srctree) source
endif
# prepare2 creates a makefile if using a separate output directory
diff --git a/README b/README
index 90a07658ede1..d6c6c742c1d7 100644
--- a/README
+++ b/README
@@ -188,7 +188,7 @@ CONFIGURING the kernel:
values to random values.
You can find more information on using the Linux kernel config tools
- in Documentation/kbuild/make-configs.txt.
+ in Documentation/kbuild/kconfig.txt.
NOTES on "make config":
- having unnecessary drivers will make the kernel bigger, and can
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index f238370c907d..8d0097f10208 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -93,8 +93,8 @@ common_shutdown_1(void *generic_ptr)
if (cpuid != boot_cpuid) {
flags |= 0x00040000UL; /* "remain halted" */
*pflags = flags;
- cpu_clear(cpuid, cpu_present_map);
- cpu_clear(cpuid, cpu_possible_map);
+ set_cpu_present(cpuid, false);
+ set_cpu_possible(cpuid, false);
halt();
}
#endif
@@ -120,8 +120,8 @@ common_shutdown_1(void *generic_ptr)
#ifdef CONFIG_SMP
/* Wait for the secondaries to halt. */
- cpu_clear(boot_cpuid, cpu_present_map);
- cpu_clear(boot_cpuid, cpu_possible_map);
+ set_cpu_present(boot_cpuid, false);
+ set_cpu_possible(boot_cpuid, false);
while (cpus_weight(cpu_present_map))
barrier();
#endif
diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c
index 00f1dc3dfd5f..b1fe5674c3a1 100644
--- a/arch/alpha/kernel/smp.c
+++ b/arch/alpha/kernel/smp.c
@@ -120,12 +120,12 @@ void __cpuinit
smp_callin(void)
{
int cpuid = hard_smp_processor_id();
- cpumask_t mask = cpu_online_map;
- if (cpu_test_and_set(cpuid, mask)) {
+ if (cpu_online(cpuid)) {
printk("??, cpu 0x%x already present??\n", cpuid);
BUG();
}
+ set_cpu_online(cpuid, true);
/* Turn on machine checks. */
wrmces(7);
@@ -436,8 +436,8 @@ setup_smp(void)
((char *)cpubase + i*hwrpb->processor_size);
if ((cpu->flags & 0x1cc) == 0x1cc) {
smp_num_probed++;
- cpu_set(i, cpu_possible_map);
- cpu_set(i, cpu_present_map);
+ set_cpu_possible(i, true);
+ set_cpu_present(i, true);
cpu->pal_revision = boot_cpu_palrev;
}
@@ -470,8 +470,8 @@ smp_prepare_cpus(unsigned int max_cpus)
/* Nothing to do on a UP box, or when told not to. */
if (smp_num_probed == 1 || max_cpus == 0) {
- cpu_possible_map = cpumask_of_cpu(boot_cpuid);
- cpu_present_map = cpumask_of_cpu(boot_cpuid);
+ init_cpu_possible(cpumask_of(boot_cpuid));
+ init_cpu_present(cpumask_of(boot_cpuid));
printk(KERN_INFO "SMP mode deactivated.\n");
return;
}
diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
index e0ee7060f9aa..98e2f3de4bc5 100644
--- a/arch/arm/configs/at91sam9260ek_defconfig
+++ b/arch/arm/configs/at91sam9260ek_defconfig
@@ -608,7 +608,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_AT91SAM9_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
#
# USB-based Watchdog Cards
diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig
index 01d1ef97d8be..149456142392 100644
--- a/arch/arm/configs/at91sam9261ek_defconfig
+++ b/arch/arm/configs/at91sam9261ek_defconfig
@@ -700,7 +700,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_AT91SAM9_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
#
# USB-based Watchdog Cards
diff --git a/arch/arm/configs/at91sam9263ek_defconfig b/arch/arm/configs/at91sam9263ek_defconfig
index 036a126725c1..21599f3c6275 100644
--- a/arch/arm/configs/at91sam9263ek_defconfig
+++ b/arch/arm/configs/at91sam9263ek_defconfig
@@ -710,7 +710,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_AT91SAM9_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
#
# USB-based Watchdog Cards
diff --git a/arch/arm/configs/at91sam9rlek_defconfig b/arch/arm/configs/at91sam9rlek_defconfig
index 237a2a6a8517..e2df81a3e804 100644
--- a/arch/arm/configs/at91sam9rlek_defconfig
+++ b/arch/arm/configs/at91sam9rlek_defconfig
@@ -606,7 +606,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
-CONFIG_AT91SAM9_WATCHDOG=y
+CONFIG_AT91SAM9X_WATCHDOG=y
#
# Sonics Silicon Backplane
diff --git a/arch/arm/configs/qil-a9260_defconfig b/arch/arm/configs/qil-a9260_defconfig
index cd1d717903ac..9b32d0eb89ba 100644
--- a/arch/arm/configs/qil-a9260_defconfig
+++ b/arch/arm/configs/qil-a9260_defconfig
@@ -727,7 +727,7 @@ CONFIG_WATCHDOG_NOWAYOUT=y
# Watchdog Device Drivers
#
# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_AT91SAM9_WATCHDOG is not set
+# CONFIG_AT91SAM9X_WATCHDOG is not set
#
# USB-based Watchdog Cards
diff --git a/arch/arm/kernel/elf.c b/arch/arm/kernel/elf.c
index 84849098c8e8..d4a0da1e48f4 100644
--- a/arch/arm/kernel/elf.c
+++ b/arch/arm/kernel/elf.c
@@ -74,9 +74,9 @@ EXPORT_SYMBOL(elf_set_personality);
*/
int arm_elf_read_implies_exec(const struct elf32_hdr *x, int executable_stack)
{
- if (executable_stack != EXSTACK_ENABLE_X)
+ if (executable_stack != EXSTACK_DISABLE_X)
return 1;
- if (cpu_architecture() <= CPU_ARCH_ARMv6)
+ if (cpu_architecture() < CPU_ARCH_ARMv6)
return 1;
return 0;
}
diff --git a/arch/arm/mach-at91/at91cap9_devices.c b/arch/arm/mach-at91/at91cap9_devices.c
index 9eca2209cde6..412aa49ad2fb 100644
--- a/arch/arm/mach-at91/at91cap9_devices.c
+++ b/arch/arm/mach-at91/at91cap9_devices.c
@@ -697,7 +697,7 @@ static void __init at91_add_device_rtt(void)
* Watchdog
* -------------------------------------------------------------------- */
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
static struct platform_device at91cap9_wdt_device = {
.name = "at91_wdt",
.id = -1,
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index fdde1ea21b07..d74c9ac007e7 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -643,7 +643,7 @@ static void __init at91_add_device_rtt(void)
* Watchdog
* -------------------------------------------------------------------- */
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
static struct platform_device at91sam9260_wdt_device = {
.name = "at91_wdt",
.id = -1,
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 17289756f80f..59fc48311fb0 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -621,7 +621,7 @@ static void __init at91_add_device_rtt(void)
* Watchdog
* -------------------------------------------------------------------- */
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
static struct platform_device at91sam9261_wdt_device = {
.name = "at91_wdt",
.id = -1,
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index b753cb879d8e..134af97ff340 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -854,7 +854,7 @@ static void __init at91_add_device_rtt(void)
* Watchdog
* -------------------------------------------------------------------- */
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
static struct platform_device at91sam9263_wdt_device = {
.name = "at91_wdt",
.id = -1,
diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c
index 145324f4ec56..728186515cdf 100644
--- a/arch/arm/mach-at91/at91sam9rl_devices.c
+++ b/arch/arm/mach-at91/at91sam9rl_devices.c
@@ -609,7 +609,7 @@ static void __init at91_add_device_rtt(void)
* Watchdog
* -------------------------------------------------------------------- */
-#if defined(CONFIG_AT91SAM9_WATCHDOG) || defined(CONFIG_AT91SAM9_WATCHDOG_MODULE)
+#if defined(CONFIG_AT91SAM9X_WATCHDOG) || defined(CONFIG_AT91SAM9X_WATCHDOG_MODULE)
static struct platform_device at91sam9rl_wdt_device = {
.name = "at91_wdt",
.id = -1,
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index 9b0447c3d59b..2f7d4977dce9 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -490,7 +490,8 @@ postcore_initcall(at91_gpio_debugfs_init);
/*--------------------------------------------------------------------------*/
-/* This lock class tells lockdep that GPIO irqs are in a different
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
* category than their parents, so it won't report false recursion.
*/
static struct lock_class_key gpio_lock_class;
@@ -509,9 +510,6 @@ void __init at91_gpio_irq_setup(void)
unsigned id = this->id;
unsigned i;
- /* enable PIO controller's clock */
- clk_enable(this->clock);
-
__raw_writel(~0, this->regbase + PIO_IDR);
for (i = 0, pin = this->chipbase; i < 32; i++, pin++) {
@@ -556,7 +554,14 @@ void __init at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
data->chipbase = PIN_BASE + i * 32;
data->regbase = data->offset + (void __iomem *)AT91_VA_BASE_SYS;
- /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
+ /* enable PIO controller's clock */
+ clk_enable(data->clock);
+
+ /*
+ * Some processors share peripheral ID between multiple GPIO banks.
+ * SAM9263 (PIOC, PIOD, PIOE)
+ * CAP9 (PIOA, PIOB, PIOC, PIOD)
+ */
if (last && last->id == data->id)
last->next = data;
}
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index fb51f0e0a83f..0b3ae21b4565 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -93,6 +93,7 @@ struct atmel_nand_data {
u8 enable_pin; /* chip enable */
u8 det_pin; /* card detect */
u8 rdy_pin; /* ready/busy */
+ u8 rdy_pin_active_low; /* rdy_pin value is inverted */
u8 ale; /* address line number connected to ALE */
u8 cle; /* address line number connected to CLE */
u8 bus_width_16; /* buswidth is 16 bit */
diff --git a/arch/arm/mach-ep93xx/include/mach/gesbc9312.h b/arch/arm/mach-ep93xx/include/mach/gesbc9312.h
deleted file mode 100644
index 21fe2b922aa5..000000000000
--- a/arch/arm/mach-ep93xx/include/mach/gesbc9312.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/*
- * arch/arm/mach-ep93xx/include/mach/gesbc9312.h
- */
diff --git a/arch/arm/mach-ep93xx/include/mach/hardware.h b/arch/arm/mach-ep93xx/include/mach/hardware.h
index 529807d182bf..2866297310b7 100644
--- a/arch/arm/mach-ep93xx/include/mach/hardware.h
+++ b/arch/arm/mach-ep93xx/include/mach/hardware.h
@@ -10,7 +10,6 @@
#include "platform.h"
-#include "gesbc9312.h"
#include "ts72xx.h"
#endif
diff --git a/arch/arm/mach-kirkwood/irq.c b/arch/arm/mach-kirkwood/irq.c
index efb86b700276..06083b23bb44 100644
--- a/arch/arm/mach-kirkwood/irq.c
+++ b/arch/arm/mach-kirkwood/irq.c
@@ -42,7 +42,7 @@ void __init kirkwood_init_irq(void)
writel(0, GPIO_EDGE_CAUSE(32));
for (i = IRQ_KIRKWOOD_GPIO_START; i < NR_IRQS; i++) {
- set_irq_chip(i, &orion_gpio_irq_level_chip);
+ set_irq_chip(i, &orion_gpio_irq_chip);
set_irq_handler(i, handle_level_irq);
irq_desc[i].status |= IRQ_LEVEL;
set_irq_flags(i, IRQF_VALID);
diff --git a/arch/arm/mach-mv78xx0/irq.c b/arch/arm/mach-mv78xx0/irq.c
index e273418797b4..30b7e4bcdbc7 100644
--- a/arch/arm/mach-mv78xx0/irq.c
+++ b/arch/arm/mach-mv78xx0/irq.c
@@ -40,7 +40,7 @@ void __init mv78xx0_init_irq(void)
writel(0, GPIO_EDGE_CAUSE(0));
for (i = IRQ_MV78XX0_GPIO_START; i < NR_IRQS; i++) {
- set_irq_chip(i, &orion_gpio_irq_level_chip);
+ set_irq_chip(i, &orion_gpio_irq_chip);
set_irq_handler(i, handle_level_irq);
irq_desc[i].status |= IRQ_LEVEL;
set_irq_flags(i, IRQF_VALID);
diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
index ad721e0cbf7a..ce4d46a4a838 100644
--- a/arch/arm/mach-omap2/clock.c
+++ b/arch/arm/mach-omap2/clock.c
@@ -565,7 +565,7 @@ u32 omap2_clksel_to_divisor(struct clk *clk, u32 field_val)
*
* Given a struct clk of a rate-selectable clksel clock, and a clock divisor,
* find the corresponding register field value. The return register value is
- * the value before left-shifting. Returns 0xffffffff on error
+ * the value before left-shifting. Returns ~0 on error
*/
u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
{
@@ -577,7 +577,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
clks = omap2_get_clksel_by_parent(clk, clk->parent);
if (clks == NULL)
- return 0;
+ return ~0;
for (clkr = clks->rates; clkr->div; clkr++) {
if ((clkr->flags & cpu_mask) && (clkr->div == div))
@@ -588,7 +588,7 @@ u32 omap2_divisor_to_clksel(struct clk *clk, u32 div)
printk(KERN_ERR "clock: Could not find divisor %d for "
"clock %s parent %s\n", div, clk->name,
clk->parent->name);
- return 0;
+ return ~0;
}
return clkr->val;
@@ -708,7 +708,7 @@ static u32 omap2_clksel_get_src_field(void __iomem **src_addr,
return 0;
for (clkr = clks->rates; clkr->div; clkr++) {
- if (clkr->flags & (cpu_mask | DEFAULT_RATE))
+ if (clkr->flags & cpu_mask && clkr->flags & DEFAULT_RATE)
break; /* Found the default rate for this platform */
}
@@ -746,7 +746,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
return -EINVAL;
if (clk->usecount > 0)
- _omap2_clk_disable(clk);
+ omap2_clk_disable(clk);
/* Set new source value (previous dividers if any in effect) */
reg_val = __raw_readl(src_addr) & ~field_mask;
@@ -759,11 +759,11 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
wmb();
}
- if (clk->usecount > 0)
- _omap2_clk_enable(clk);
-
clk->parent = new_parent;
+ if (clk->usecount > 0)
+ omap2_clk_enable(clk);
+
/* CLKSEL clocks follow their parents' rates, divided by a divisor */
clk->rate = new_parent->rate;
diff --git a/arch/arm/mach-orion5x/irq.c b/arch/arm/mach-orion5x/irq.c
index 0caae43301e5..e03f7b45cb0d 100644
--- a/arch/arm/mach-orion5x/irq.c
+++ b/arch/arm/mach-orion5x/irq.c
@@ -44,7 +44,7 @@ void __init orion5x_init_irq(void)
* User can use set_type() if he wants to use edge types handlers.
*/
for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
- set_irq_chip(i, &orion_gpio_irq_level_chip);
+ set_irq_chip(i, &orion_gpio_irq_chip);
set_irq_handler(i, handle_level_irq);
irq_desc[i].status |= IRQ_LEVEL;
set_irq_flags(i, IRQF_VALID);
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 9b36c5cb5e9f..d4d082c5c2d4 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -693,7 +693,8 @@ static void __init sanity_check_meminfo(void)
* Check whether this memory bank would entirely overlap
* the vmalloc area.
*/
- if (__va(bank->start) >= VMALLOC_MIN) {
+ if (__va(bank->start) >= VMALLOC_MIN ||
+ __va(bank->start) < PAGE_OFFSET) {
printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx "
"(vmalloc region overlap).\n",
bank->start, bank->start + bank->size - 1);
diff --git a/arch/arm/plat-orion/gpio.c b/arch/arm/plat-orion/gpio.c
index 967186425ca1..0d12c2164766 100644
--- a/arch/arm/plat-orion/gpio.c
+++ b/arch/arm/plat-orion/gpio.c
@@ -265,51 +265,36 @@ EXPORT_SYMBOL(orion_gpio_set_blink);
* polarity LEVEL mask
*
****************************************************************************/
-static void gpio_irq_edge_ack(u32 irq)
-{
- int pin = irq_to_gpio(irq);
-
- writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin));
-}
-
-static void gpio_irq_edge_mask(u32 irq)
-{
- int pin = irq_to_gpio(irq);
- u32 u;
-
- u = readl(GPIO_EDGE_MASK(pin));
- u &= ~(1 << (pin & 31));
- writel(u, GPIO_EDGE_MASK(pin));
-}
-static void gpio_irq_edge_unmask(u32 irq)
+static void gpio_irq_ack(u32 irq)
{
- int pin = irq_to_gpio(irq);
- u32 u;
-
- u = readl(GPIO_EDGE_MASK(pin));
- u |= 1 << (pin & 31);
- writel(u, GPIO_EDGE_MASK(pin));
+ int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
+ int pin = irq_to_gpio(irq);
+ writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin));
+ }
}
-static void gpio_irq_level_mask(u32 irq)
+static void gpio_irq_mask(u32 irq)
{
int pin = irq_to_gpio(irq);
- u32 u;
-
- u = readl(GPIO_LEVEL_MASK(pin));
+ int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+ u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
+ GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
+ u32 u = readl(reg);
u &= ~(1 << (pin & 31));
- writel(u, GPIO_LEVEL_MASK(pin));
+ writel(u, reg);
}
-static void gpio_irq_level_unmask(u32 irq)
+static void gpio_irq_unmask(u32 irq)
{
int pin = irq_to_gpio(irq);
- u32 u;
-
- u = readl(GPIO_LEVEL_MASK(pin));
+ int type = irq_desc[irq].status & IRQ_TYPE_SENSE_MASK;
+ u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
+ GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
+ u32 u = readl(reg);
u |= 1 << (pin & 31);
- writel(u, GPIO_LEVEL_MASK(pin));
+ writel(u, reg);
}
static int gpio_irq_set_type(u32 irq, u32 type)
@@ -331,9 +316,9 @@ static int gpio_irq_set_type(u32 irq, u32 type)
* Set edge/level type.
*/
if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
- desc->chip = &orion_gpio_irq_edge_chip;
+ desc->handle_irq = handle_edge_irq;
} else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
- desc->chip = &orion_gpio_irq_level_chip;
+ desc->handle_irq = handle_level_irq;
} else {
printk(KERN_ERR "failed to set irq=%d (type=%d)\n", irq, type);
return -EINVAL;
@@ -371,19 +356,11 @@ static int gpio_irq_set_type(u32 irq, u32 type)
return 0;
}
-struct irq_chip orion_gpio_irq_edge_chip = {
- .name = "orion_gpio_irq_edge",
- .ack = gpio_irq_edge_ack,
- .mask = gpio_irq_edge_mask,
- .unmask = gpio_irq_edge_unmask,
- .set_type = gpio_irq_set_type,
-};
-
-struct irq_chip orion_gpio_irq_level_chip = {
- .name = "orion_gpio_irq_level",
- .mask = gpio_irq_level_mask,
- .mask_ack = gpio_irq_level_mask,
- .unmask = gpio_irq_level_unmask,
+struct irq_chip orion_gpio_irq_chip = {
+ .name = "orion_gpio",
+ .ack = gpio_irq_ack,
+ .mask = gpio_irq_mask,
+ .unmask = gpio_irq_unmask,
.set_type = gpio_irq_set_type,
};
diff --git a/arch/arm/plat-orion/include/plat/gpio.h b/arch/arm/plat-orion/include/plat/gpio.h
index 54deaf274b52..ec743e82c876 100644
--- a/arch/arm/plat-orion/include/plat/gpio.h
+++ b/arch/arm/plat-orion/include/plat/gpio.h
@@ -31,8 +31,7 @@ void orion_gpio_set_blink(unsigned pin, int blink);
/*
* GPIO interrupt handling.
*/
-extern struct irq_chip orion_gpio_irq_edge_chip;
-extern struct irq_chip orion_gpio_irq_level_chip;
+extern struct irq_chip orion_gpio_irq_chip;
void orion_gpio_irq_handler(int irqoff);
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h
index aafaf7a78886..cff8e84f78f2 100644
--- a/arch/avr32/mach-at32ap/include/mach/board.h
+++ b/arch/avr32/mach-at32ap/include/mach/board.h
@@ -116,6 +116,7 @@ struct atmel_nand_data {
int enable_pin; /* chip enable */
int det_pin; /* card detect */
int rdy_pin; /* ready/busy */
+ u8 rdy_pin_active_low; /* rdy_pin value is inverted */
u8 ale; /* address line number connected to ALE */
u8 cle; /* address line number connected to CLE */
u8 bus_width_16; /* buswidth is 16 bit */
diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig
index 6183aeccecf1..4eb45c012498 100644
--- a/arch/ia64/Kconfig
+++ b/arch/ia64/Kconfig
@@ -221,7 +221,11 @@ config IA64_HP_SIM
config IA64_XEN_GUEST
bool "Xen guest"
+ select SWIOTLB
depends on XEN
+ help
+ Build a kernel that runs on Xen guest domain. At this moment only
+ 16KB page size in supported.
endchoice
@@ -479,8 +483,7 @@ config HOLES_IN_ZONE
default y if VIRTUAL_MEM_MAP
config HAVE_ARCH_EARLY_PFN_TO_NID
- def_bool y
- depends on NEED_MULTIPLE_NODES
+ def_bool NUMA && SPARSEMEM
config HAVE_ARCH_NODEDATA_EXTENSION
def_bool y
diff --git a/arch/ia64/configs/xen_domu_defconfig b/arch/ia64/configs/xen_domu_defconfig
new file mode 100644
index 000000000000..0bb0714dc19d
--- /dev/null
+++ b/arch/ia64/configs/xen_domu_defconfig
@@ -0,0 +1,1601 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.29-rc1
+# Fri Jan 16 11:49:59 2009
+#
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=20
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+# CONFIG_GROUP_SCHED is not set
+
+#
+# Control Group support
+#
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+# CONFIG_EMBEDDED is not set
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_KALLSYMS_STRIP_GENERATED=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_COMPAT_BRK=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_USE_GENERIC_SMP_HELPERS=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_STOP_MACHINE=y
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_IA64=y
+CONFIG_64BIT=y
+CONFIG_ZONE_DMA=y
+CONFIG_QUICKLIST=y
+CONFIG_MMU=y
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_HUGETLB_PAGE_SIZE_VARIABLE=y
+CONFIG_GENERIC_FIND_NEXT_BIT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_DMI=y
+CONFIG_EFI=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_PARAVIRT_GUEST=y
+CONFIG_PARAVIRT=y
+CONFIG_XEN=y
+CONFIG_XEN_XENCOMM=y
+CONFIG_NO_IDLE_HZ=y
+# CONFIG_IA64_GENERIC is not set
+# CONFIG_IA64_DIG is not set
+# CONFIG_IA64_DIG_VTD is not set
+# CONFIG_IA64_HP_ZX1 is not set
+# CONFIG_IA64_HP_ZX1_SWIOTLB is not set
+# CONFIG_IA64_SGI_SN2 is not set
+# CONFIG_IA64_SGI_UV is not set
+# CONFIG_IA64_HP_SIM is not set
+CONFIG_IA64_XEN_GUEST=y
+# CONFIG_ITANIUM is not set
+CONFIG_MCKINLEY=y
+# CONFIG_IA64_PAGE_SIZE_4KB is not set
+# CONFIG_IA64_PAGE_SIZE_8KB is not set
+CONFIG_IA64_PAGE_SIZE_16KB=y
+# CONFIG_IA64_PAGE_SIZE_64KB is not set
+CONFIG_PGTABLE_3=y
+# CONFIG_PGTABLE_4 is not set
+CONFIG_HZ=250
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_SCHED_HRTICK is not set
+CONFIG_IA64_L1_CACHE_SHIFT=7
+CONFIG_IA64_CYCLONE=y
+CONFIG_IOSAPIC=y
+CONFIG_FORCE_MAX_ZONEORDER=17
+# CONFIG_VIRT_CPU_ACCOUNTING is not set
+CONFIG_SMP=y
+CONFIG_NR_CPUS=16
+CONFIG_HOTPLUG_CPU=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+# CONFIG_SCHED_SMT is not set
+CONFIG_PERMIT_BSP_REMOVE=y
+CONFIG_FORCE_CPEI_RETARGET=y
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_NR_QUICK=1
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
+CONFIG_ARCH_FLATMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_POPULATES_NODE_MAP=y
+CONFIG_VIRTUAL_MEM_MAP=y
+CONFIG_HOLES_IN_ZONE=y
+# CONFIG_IA32_SUPPORT is not set
+# CONFIG_COMPAT_FOR_U64_ALIGNMENT is not set
+CONFIG_IA64_MCA_RECOVERY=y
+CONFIG_PERFMON=y
+CONFIG_IA64_PALINFO=y
+# CONFIG_IA64_MC_ERR_INJECT is not set
+# CONFIG_IA64_ESI is not set
+# CONFIG_IA64_HP_AML_NFW is not set
+CONFIG_KEXEC=y
+# CONFIG_CRASH_DUMP is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+CONFIG_EFI_VARS=y
+CONFIG_EFI_PCDP=y
+CONFIG_DMIID=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+
+#
+# Power management and ACPI options
+#
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_ACPI=y
+CONFIG_ACPI_SLEEP=y
+CONFIG_ACPI_PROCFS=y
+CONFIG_ACPI_PROCFS_POWER=y
+CONFIG_ACPI_SYSFS_POWER=y
+CONFIG_ACPI_PROC_EVENT=y
+CONFIG_ACPI_BUTTON=m
+CONFIG_ACPI_FAN=m
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=m
+CONFIG_ACPI_HOTPLUG_CPU=y
+CONFIG_ACPI_THERMAL=m
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
+# CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PCI_SLOT is not set
+CONFIG_ACPI_SYSTEM=y
+CONFIG_ACPI_CONTAINER=m
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# Bus options (PCI, PCMCIA)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_SYSCALL=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_ARCH_SUPPORTS_MSI=y
+# CONFIG_PCI_MSI is not set
+CONFIG_PCI_LEGACY=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+CONFIG_HOTPLUG_PCI=m
+# CONFIG_HOTPLUG_PCI_FAKE is not set
+CONFIG_HOTPLUG_PCI_ACPI=m
+# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set
+# CONFIG_HOTPLUG_PCI_CPCI is not set
+# CONFIG_HOTPLUG_PCI_SHPC is not set
+# CONFIG_PCCARD is not set
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_NET_NS is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+CONFIG_ARPD=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_PHONET is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=4096
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_XEN_BLKDEV_FRONTEND=y
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_C2PORT is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=y
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_TIMINGS=y
+CONFIG_IDE_ATAPI=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=y
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDECD_VERBOSE_ERRORS=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEACPI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_BLK_DEV_PLATFORM is not set
+# CONFIG_BLK_DEV_IDEPNP is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+
+#
+# PCI IDE chipsets support
+#
+CONFIG_BLK_DEV_IDEPCI=y
+CONFIG_IDEPCI_PCIBUS_ORDER=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+CONFIG_BLK_DEV_CMD64X=y
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+CONFIG_BLK_DEV_PIIX=y
+# CONFIG_BLK_DEV_IT8172 is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+CONFIG_SCSI_NETLINK=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_ST=m
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=m
+# CONFIG_BLK_DEV_SR_VENDOR is not set
+CONFIG_CHR_DEV_SG=m
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=y
+CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_FCOE is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_STEX is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+CONFIG_SCSI_SYM53C8XX_MMIO=y
+CONFIG_SCSI_QLOGIC_1280=y
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_ATA is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+# CONFIG_MD_RAID10 is not set
+# CONFIG_MD_RAID456 is not set
+CONFIG_MD_MULTIPATH=m
+# CONFIG_MD_FAULTY is not set
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+CONFIG_FUSION=y
+CONFIG_FUSION_SPI=y
+CONFIG_FUSION_FC=y
+# CONFIG_FUSION_SAS is not set
+CONFIG_FUSION_MAX_SGE=128
+CONFIG_FUSION_CTL=y
+# CONFIG_FUSION_LOGGING is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_IEEE1394 is not set
+# CONFIG_I2O is not set
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_ARCNET is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=m
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_ULI526X is not set
+# CONFIG_HP100 is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+CONFIG_E100=m
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R6040 is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
+CONFIG_NETDEV_1000=y
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+CONFIG_E1000=y
+# CONFIG_E1000E is not set
+# CONFIG_IP1000 is not set
+# CONFIG_IGB is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_R8169 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+# CONFIG_BNX2 is not set
+# CONFIG_QLA3XXX is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_JME is not set
+CONFIG_NETDEV_10000=y
+# CONFIG_CHELSIO_T1 is not set
+CONFIG_CHELSIO_T3_DEPENDS=y
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_ENIC is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+# CONFIG_MYRI10GE is not set
+# CONFIG_NETXEN_NIC is not set
+# CONFIG_NIU is not set
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_TEHUTI is not set
+# CONFIG_BNX2X is not set
+# CONFIG_QLGE is not set
+# CONFIG_SFC is not set
+# CONFIG_TR is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_XEN_NETDEV_FRONTEND=y
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+CONFIG_GAMEPORT=m
+# CONFIG_GAMEPORT_NS558 is not set
+# CONFIG_GAMEPORT_L4 is not set
+# CONFIG_GAMEPORT_EMU10K1 is not set
+# CONFIG_GAMEPORT_FM801 is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+CONFIG_SERIAL_NONSTANDARD=y
+# CONFIG_COMPUTONE is not set
+# CONFIG_ROCKETPORT is not set
+# CONFIG_CYCLADES is not set
+# CONFIG_DIGIEPCA is not set
+# CONFIG_MOXA_INTELLIO is not set
+# CONFIG_MOXA_SMARTIO is not set
+# CONFIG_ISI is not set
+# CONFIG_SYNCLINKMP is not set
+# CONFIG_SYNCLINK_GT is not set
+# CONFIG_N_HDLC is not set
+# CONFIG_RISCOM8 is not set
+# CONFIG_SPECIALIX is not set
+# CONFIG_SX is not set
+# CONFIG_RIO is not set
+# CONFIG_STALDRV is not set
+# CONFIG_NOZOMI is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_PCI=y
+CONFIG_SERIAL_8250_PNP=y
+CONFIG_SERIAL_8250_NR_UARTS=6
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+# CONFIG_SERIAL_8250_DETECT_IRQ is not set
+# CONFIG_SERIAL_8250_RSA is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_JSM is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_HVC_DRIVER=y
+CONFIG_HVC_IRQ=y
+CONFIG_HVC_XEN=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_EFI_RTC=y
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+CONFIG_RAW_DRIVER=m
+CONFIG_MAX_RAW_DEVS=256
+CONFIG_HPET=y
+CONFIG_HPET_MMAP=y
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+CONFIG_I2C=m
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=m
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# PC SMBus host controller drivers
+#
+# CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
+# CONFIG_I2C_ALI15X3 is not set
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+# CONFIG_I2C_I801 is not set
+# CONFIG_I2C_ISCH is not set
+# CONFIG_I2C_PIIX4 is not set
+# CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_SIS5595 is not set
+# CONFIG_I2C_SIS630 is not set
+# CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_VIA is not set
+# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
+# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_AT24 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_PCF8575 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_THERMAL=m
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_REGULATOR is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+CONFIG_AGP=m
+CONFIG_DRM=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+CONFIG_DRM_MGA=m
+CONFIG_DRM_SIS=m
+# CONFIG_DRM_VIA is not set
+# CONFIG_DRM_SAVAGE is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+CONFIG_HID_EZKEY=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_LOGITECH=y
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+# CONFIG_GREENASIA_FF is not set
+CONFIG_HID_TOPSEED=y
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+CONFIG_USB_OHCI_HCD=m
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+#
+
+#
+# see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_UIO is not set
+CONFIG_XEN_BALLOON=y
+CONFIG_XEN_SCRUB_PAGES=y
+CONFIG_XENFS=y
+CONFIG_XEN_COMPAT_XENFS=y
+# CONFIG_STAGING is not set
+# CONFIG_MSPEC is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=y
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+# CONFIG_MSDOS_FS is not set
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+# CONFIG_NTFS_RW is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+CONFIG_NFSD_V4=y
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+# CONFIG_SUNRPC_REGISTER_V4 is not set
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+CONFIG_SMB_NLS_DEFAULT=y
+CONFIG_SMB_NLS_REMOTE="cp437"
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=2048
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+
+#
+# Tracers
+#
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_IA64_GRANULE_16MB=y
+# CONFIG_IA64_GRANULE_64MB is not set
+# CONFIG_IA64_PRINT_HAZARDS is not set
+# CONFIG_DISABLE_VHPT is not set
+# CONFIG_IA64_DEBUG_CMPXCHG is not set
+# CONFIG_IA64_DEBUG_IRQ is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=m
+# CONFIG_CRYPTO_LRW is not set
+CONFIG_CRYPTO_PCBC=m
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=m
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+# CONFIG_VIRTIO_PCI is not set
+# CONFIG_VIRTIO_BALLOON is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_PENDING_IRQ=y
+CONFIG_IRQ_PER_CPU=y
+# CONFIG_IOMMU_API is not set
diff --git a/arch/ia64/include/asm/kvm.h b/arch/ia64/include/asm/kvm.h
index 116761ca462d..2b0a38e84705 100644
--- a/arch/ia64/include/asm/kvm.h
+++ b/arch/ia64/include/asm/kvm.h
@@ -24,6 +24,10 @@
#include <linux/types.h>
#include <linux/ioctl.h>
+/* Select x86 specific features in <linux/kvm.h> */
+#define __KVM_HAVE_IOAPIC
+#define __KVM_HAVE_DEVICE_ASSIGNMENT
+
/* Architectural interrupt line count. */
#define KVM_NR_INTERRUPTS 256
diff --git a/arch/ia64/include/asm/mmzone.h b/arch/ia64/include/asm/mmzone.h
index 34efe88eb849..f2ca32069b3f 100644
--- a/arch/ia64/include/asm/mmzone.h
+++ b/arch/ia64/include/asm/mmzone.h
@@ -31,10 +31,6 @@ static inline int pfn_to_nid(unsigned long pfn)
#endif
}
-#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
-extern int early_pfn_to_nid(unsigned long pfn);
-#endif
-
#ifdef CONFIG_IA64_DIG /* DIG systems are small */
# define MAX_PHYSNODE_ID 8
# define NR_NODE_MEMBLKS (MAX_NUMNODES * 8)
diff --git a/arch/ia64/include/asm/sn/bte.h b/arch/ia64/include/asm/sn/bte.h
index 5efecf06c9a4..96798d2da7c2 100644
--- a/arch/ia64/include/asm/sn/bte.h
+++ b/arch/ia64/include/asm/sn/bte.h
@@ -39,7 +39,7 @@
/* BTE status register only supports 16 bits for length field */
#define BTE_LEN_BITS (16)
#define BTE_LEN_MASK ((1 << BTE_LEN_BITS) - 1)
-#define BTE_MAX_XFER ((1 << BTE_LEN_BITS) * L1_CACHE_BYTES)
+#define BTE_MAX_XFER (BTE_LEN_MASK << L1_CACHE_SHIFT)
/* Define hardware */
diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c
index 11463994a7d5..52290547c85b 100644
--- a/arch/ia64/kernel/smpboot.c
+++ b/arch/ia64/kernel/smpboot.c
@@ -736,14 +736,15 @@ int __cpu_disable(void)
return -EBUSY;
}
+ cpu_clear(cpu, cpu_online_map);
+
if (migrate_platform_irqs(cpu)) {
cpu_set(cpu, cpu_online_map);
- return (-EBUSY);
+ return -EBUSY;
}
remove_siblinginfo(cpu);
fixup_irqs();
- cpu_clear(cpu, cpu_online_map);
local_flush_tlb_all();
cpu_clear(cpu, cpu_callin_map);
return 0;
diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c
index 4e586f6110aa..28f982045f29 100644
--- a/arch/ia64/kvm/kvm-ia64.c
+++ b/arch/ia64/kvm/kvm-ia64.c
@@ -1337,6 +1337,10 @@ static void kvm_release_vm_pages(struct kvm *kvm)
}
}
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvm_iommu_unmap_guest(kvm);
diff --git a/arch/ia64/kvm/process.c b/arch/ia64/kvm/process.c
index 552d07724207..230eae482f32 100644
--- a/arch/ia64/kvm/process.c
+++ b/arch/ia64/kvm/process.c
@@ -455,13 +455,18 @@ fpswa_ret_t vmm_fp_emulate(int fp_fault, void *bundle, unsigned long *ipsr,
if (!vmm_fpswa_interface)
return (fpswa_ret_t) {-1, 0, 0, 0};
- /*
- * Just let fpswa driver to use hardware fp registers.
- * No fp register is valid in memory.
- */
memset(&fp_state, 0, sizeof(fp_state_t));
/*
+ * compute fp_state. only FP registers f6 - f11 are used by the
+ * vmm, so set those bits in the mask and set the low volatile
+ * pointer to point to these registers.
+ */
+ fp_state.bitmask_low64 = 0xfc0; /* bit6..bit11 */
+
+ fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;
+
+ /*
* unsigned long (*EFI_FPSWA) (
* unsigned long trap_type,
* void *Bundle,
@@ -545,10 +550,6 @@ void reflect_interruption(u64 ifa, u64 isr, u64 iim,
status = vmm_handle_fpu_swa(0, regs, isr);
if (!status)
return ;
- else if (-EAGAIN == status) {
- vcpu_decrement_iip(vcpu);
- return ;
- }
break;
}
diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c
index b73bf1838e57..3efea7d0a351 100644
--- a/arch/ia64/mm/numa.c
+++ b/arch/ia64/mm/numa.c
@@ -58,7 +58,7 @@ paddr_to_nid(unsigned long paddr)
* SPARSEMEM to allocate the SPARSEMEM sectionmap on the NUMA node where
* the section resides.
*/
-int early_pfn_to_nid(unsigned long pfn)
+int __meminit __early_pfn_to_nid(unsigned long pfn)
{
int i, section = pfn >> PFN_SECTION_SHIFT, ssec, esec;
@@ -70,7 +70,7 @@ int early_pfn_to_nid(unsigned long pfn)
return node_memblk[i].nid;
}
- return 0;
+ return -1;
}
#ifdef CONFIG_MEMORY_HOTPLUG
diff --git a/arch/ia64/sn/kernel/bte.c b/arch/ia64/sn/kernel/bte.c
index 9456d4034024..c6d6b62db66c 100644
--- a/arch/ia64/sn/kernel/bte.c
+++ b/arch/ia64/sn/kernel/bte.c
@@ -97,9 +97,10 @@ bte_result_t bte_copy(u64 src, u64 dest, u64 len, u64 mode, void *notification)
return BTE_SUCCESS;
}
- BUG_ON((len & L1_CACHE_MASK) ||
- (src & L1_CACHE_MASK) || (dest & L1_CACHE_MASK));
- BUG_ON(!(len < ((BTE_LEN_MASK + 1) << L1_CACHE_SHIFT)));
+ BUG_ON(len & L1_CACHE_MASK);
+ BUG_ON(src & L1_CACHE_MASK);
+ BUG_ON(dest & L1_CACHE_MASK);
+ BUG_ON(len > BTE_MAX_XFER);
/*
* Start with interface corresponding to cpu number
diff --git a/arch/ia64/xen/Kconfig b/arch/ia64/xen/Kconfig
index f1683a20275b..515e0826803a 100644
--- a/arch/ia64/xen/Kconfig
+++ b/arch/ia64/xen/Kconfig
@@ -8,8 +8,7 @@ config XEN
depends on PARAVIRT && MCKINLEY && IA64_PAGE_SIZE_16KB && EXPERIMENTAL
select XEN_XENCOMM
select NO_IDLE_HZ
-
- # those are required to save/restore.
+ # followings are required to save/restore.
select ARCH_SUSPEND_POSSIBLE
select SUSPEND
select PM_SLEEP
diff --git a/arch/ia64/xen/xen_pv_ops.c b/arch/ia64/xen/xen_pv_ops.c
index 04cd12350455..936cff3c96e0 100644
--- a/arch/ia64/xen/xen_pv_ops.c
+++ b/arch/ia64/xen/xen_pv_ops.c
@@ -153,7 +153,7 @@ xen_post_smp_prepare_boot_cpu(void)
xen_setup_vcpu_info_placement();
}
-static const struct pv_init_ops xen_init_ops __initdata = {
+static const struct pv_init_ops xen_init_ops __initconst = {
.banner = xen_banner,
.reserve_memory = xen_reserve_memory,
@@ -337,7 +337,7 @@ xen_iosapic_write(char __iomem *iosapic, unsigned int reg, u32 val)
HYPERVISOR_physdev_op(PHYSDEVOP_apic_write, &apic_op);
}
-static const struct pv_iosapic_ops xen_iosapic_ops __initdata = {
+static const struct pv_iosapic_ops xen_iosapic_ops __initconst = {
.pcat_compat_init = xen_pcat_compat_init,
.__get_irq_chip = xen_iosapic_get_irq_chip,
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index dba4afabb444..39478dd08e67 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -187,8 +187,8 @@ __asm__ (__ALIGN_STR "\n" \
" 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 : &mfp.int_mk_a) \
- : (n & 16 ? &tt_mfp.int_mk_b : &mfp.int_mk_b)), \
+ "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 */ \
@@ -366,14 +366,14 @@ void __init atari_init_IRQ(void)
/* Initialize the MFP(s) */
#ifdef ATARI_USE_SOFTWARE_EOI
- mfp.vec_adr = 0x48; /* Software EOI-Mode */
+ st_mfp.vec_adr = 0x48; /* Software EOI-Mode */
#else
- mfp.vec_adr = 0x40; /* Automatic EOI-Mode */
+ st_mfp.vec_adr = 0x40; /* Automatic EOI-Mode */
#endif
- mfp.int_en_a = 0x00; /* turn off MFP-Ints */
- mfp.int_en_b = 0x00;
- mfp.int_mk_a = 0xff; /* no Masking */
- mfp.int_mk_b = 0xff;
+ st_mfp.int_en_a = 0x00; /* turn off MFP-Ints */
+ st_mfp.int_en_b = 0x00;
+ st_mfp.int_mk_a = 0xff; /* no Masking */
+ st_mfp.int_mk_b = 0xff;
if (ATARIHW_PRESENT(TT_MFP)) {
#ifdef ATARI_USE_SOFTWARE_EOI
diff --git a/arch/m68k/atari/atakeyb.c b/arch/m68k/atari/atakeyb.c
index a5f33c059979..4add96d13b19 100644
--- a/arch/m68k/atari/atakeyb.c
+++ b/arch/m68k/atari/atakeyb.c
@@ -609,10 +609,10 @@ int atari_keyb_init(void)
ACIA_RHTID : 0);
/* make sure the interrupt line is up */
- } while ((mfp.par_dt_reg & 0x10) == 0);
+ } while ((st_mfp.par_dt_reg & 0x10) == 0);
/* enable ACIA Interrupts */
- mfp.active_edge &= ~0x10;
+ st_mfp.active_edge &= ~0x10;
atari_turnon_irq(IRQ_MFP_ACIA);
ikbd_self_test = 1;
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index 49c28cdbea5c..ae2d96e5d618 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -258,7 +258,7 @@ void __init config_atari(void)
printk("STND_SHIFTER ");
}
}
- if (hwreg_present(&mfp.par_dt_reg)) {
+ if (hwreg_present(&st_mfp.par_dt_reg)) {
ATARIHW_SET(ST_MFP);
printk("ST_MFP ");
}
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index 702b15ccfab7..28efdc33c1ae 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -34,9 +34,9 @@ static struct console atari_console_driver = {
static inline void ata_mfp_out(char c)
{
- while (!(mfp.trn_stat & 0x80)) /* wait for tx buf empty */
+ while (!(st_mfp.trn_stat & 0x80)) /* wait for tx buf empty */
barrier();
- mfp.usart_dta = c;
+ st_mfp.usart_dta = c;
}
static void atari_mfp_console_write(struct console *co, const char *str,
@@ -91,7 +91,7 @@ static int ata_par_out(char c)
/* This a some-seconds timeout in case no printer is connected */
unsigned long i = loops_per_jiffy > 1 ? loops_per_jiffy : 10000000/HZ;
- while ((mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
+ while ((st_mfp.par_dt_reg & 1) && --i) /* wait for BUSY == L */
;
if (!i)
return 0;
@@ -131,9 +131,9 @@ static void atari_par_console_write(struct console *co, const char *str,
#if 0
int atari_mfp_console_wait_key(struct console *co)
{
- while (!(mfp.rcv_stat & 0x80)) /* wait for rx buf filled */
+ while (!(st_mfp.rcv_stat & 0x80)) /* wait for rx buf filled */
barrier();
- return mfp.usart_dta;
+ return st_mfp.usart_dta;
}
int atari_scc_console_wait_key(struct console *co)
@@ -175,12 +175,12 @@ static void __init atari_init_mfp_port(int cflag)
baud = B9600; /* use default 9600bps for non-implemented rates */
baud -= B1200; /* baud_table[] starts at 1200bps */
- mfp.trn_stat &= ~0x01; /* disable TX */
- mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
- mfp.tim_ct_cd &= 0x70; /* stop timer D */
- mfp.tim_dt_d = baud_table[baud];
- mfp.tim_ct_cd |= 0x01; /* start timer D, 1:4 */
- mfp.trn_stat |= 0x01; /* enable TX */
+ st_mfp.trn_stat &= ~0x01; /* disable TX */
+ st_mfp.usart_ctr = parity | csize | 0x88; /* 1:16 clk mode, 1 stop bit */
+ st_mfp.tim_ct_cd &= 0x70; /* stop timer D */
+ st_mfp.tim_dt_d = baud_table[baud];
+ st_mfp.tim_ct_cd |= 0x01; /* start timer D, 1:4 */
+ st_mfp.trn_stat |= 0x01; /* enable TX */
}
#define SCC_WRITE(reg, val) \
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index d076ff8d1b39..a0531f34c617 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -27,9 +27,9 @@ void __init
atari_sched_init(irq_handler_t timer_routine)
{
/* set Timer C data Register */
- mfp.tim_dt_c = INT_TICKS;
+ st_mfp.tim_dt_c = INT_TICKS;
/* start timer C, div = 1:100 */
- mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
+ st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 15) | 0x60;
/* install interrupt service routine for MFP Timer C */
if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
"timer", timer_routine))
@@ -46,11 +46,11 @@ unsigned long atari_gettimeoffset (void)
unsigned long ticks, offset = 0;
/* read MFP timer C current value */
- ticks = mfp.tim_dt_c;
+ ticks = st_mfp.tim_dt_c;
/* The probability of underflow is less than 2% */
if (ticks > INT_TICKS - INT_TICKS / 50)
/* Check for pending timer interrupt */
- if (mfp.int_pn_b & (1 << 5))
+ if (st_mfp.int_pn_b & (1 << 5))
offset = TICK_SIZE;
ticks = INT_TICKS - ticks;
diff --git a/arch/m68k/include/asm/atarihw.h b/arch/m68k/include/asm/atarihw.h
index 1412b4ab202f..a714e1aa072a 100644
--- a/arch/m68k/include/asm/atarihw.h
+++ b/arch/m68k/include/asm/atarihw.h
@@ -113,7 +113,7 @@ extern struct atari_hw_present atari_hw_present;
* of nops on various machines. Somebody claimed that the tstb takes 600 ns.
*/
#define MFPDELAY() \
- __asm__ __volatile__ ( "tstb %0" : : "m" (mfp.par_dt_reg) : "cc" );
+ __asm__ __volatile__ ( "tstb %0" : : "m" (st_mfp.par_dt_reg) : "cc" );
/* Do cache push/invalidate for DMA read/write. This function obeys the
* snooping on some machines (Medusa) and processors: The Medusa itself can
@@ -565,7 +565,7 @@ struct MFP
u_char char_dummy23;
u_char usart_dta;
};
-# define mfp ((*(volatile struct MFP*)MFP_BAS))
+# define st_mfp ((*(volatile struct MFP*)MFP_BAS))
/* TT's second MFP */
diff --git a/arch/m68k/include/asm/atariints.h b/arch/m68k/include/asm/atariints.h
index 5748e99f4e26..f597892e43a0 100644
--- a/arch/m68k/include/asm/atariints.h
+++ b/arch/m68k/include/asm/atariints.h
@@ -113,7 +113,7 @@ static inline int get_mfp_bit( unsigned irq, int type )
{ unsigned char mask, *reg;
mask = 1 << (irq & 7);
- reg = (unsigned char *)&mfp.int_en_a + type*4 +
+ reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
((irq & 8) >> 2) + (((irq-8) & 16) << 3);
return( *reg & mask );
}
@@ -123,7 +123,7 @@ static inline void set_mfp_bit( unsigned irq, int type )
{ unsigned char mask, *reg;
mask = 1 << (irq & 7);
- reg = (unsigned char *)&mfp.int_en_a + type*4 +
+ reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
((irq & 8) >> 2) + (((irq-8) & 16) << 3);
__asm__ __volatile__ ( "orb %0,%1"
: : "di" (mask), "m" (*reg) : "memory" );
@@ -134,7 +134,7 @@ static inline void clear_mfp_bit( unsigned irq, int type )
{ unsigned char mask, *reg;
mask = ~(1 << (irq & 7));
- reg = (unsigned char *)&mfp.int_en_a + type*4 +
+ reg = (unsigned char *)&st_mfp.int_en_a + type*4 +
((irq & 8) >> 2) + (((irq-8) & 16) << 3);
if (type == MFP_PENDING || type == MFP_SERVICE)
__asm__ __volatile__ ( "moveb %0,%1"
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index 9a9f43358879..41d16822e616 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -7,6 +7,7 @@ mainmenu "Linux Kernel Configuration"
config MN10300
def_bool y
+ select HAVE_OPROFILE
config AM33
def_bool y
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
index 1a86425fec42..07dbbcda3b2e 100644
--- a/arch/mn10300/unit-asb2305/pci.c
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -173,7 +173,7 @@ static int pci_ampci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
BRIDGEREGB(where) = value;
} else {
if (bus->number == 0 &&
- (devfn == PCI_DEVFN(2, 0) && devfn == PCI_DEVFN(3, 0))
+ (devfn == PCI_DEVFN(2, 0) || devfn == PCI_DEVFN(3, 0))
)
__pcidebug("<= %02x", bus, devfn, where, value);
CONFIG_ADDRESS = CONFIG_CMD(bus, devfn, where);
diff --git a/arch/powerpc/include/asm/pgtable-4k.h b/arch/powerpc/include/asm/pgtable-4k.h
index 6b18ba9d2d85..1dbca4e7de67 100644
--- a/arch/powerpc/include/asm/pgtable-4k.h
+++ b/arch/powerpc/include/asm/pgtable-4k.h
@@ -60,7 +60,7 @@
/* It should be preserving the high 48 bits and then specifically */
/* preserving _PAGE_SECONDARY | _PAGE_GROUP_IX */
#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
- _PAGE_HPTEFLAGS)
+ _PAGE_HPTEFLAGS | _PAGE_SPECIAL)
/* Bits to mask out from a PMD to get to the PTE page */
#define PMD_MASKED_BITS 0
diff --git a/arch/powerpc/include/asm/pgtable-64k.h b/arch/powerpc/include/asm/pgtable-64k.h
index 07b0d8f09cb6..7389003349a6 100644
--- a/arch/powerpc/include/asm/pgtable-64k.h
+++ b/arch/powerpc/include/asm/pgtable-64k.h
@@ -114,7 +114,7 @@ static inline struct subpage_prot_table *pgd_subpage_prot(pgd_t *pgd)
* pgprot changes
*/
#define _PAGE_CHG_MASK (PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
- _PAGE_ACCESSED)
+ _PAGE_ACCESSED | _PAGE_SPECIAL)
/* Bits to mask out from a PMD to get to the PTE page */
#define PMD_MASKED_BITS 0x1ff
diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
index f69a4d977729..820b5f0a35ce 100644
--- a/arch/powerpc/include/asm/pgtable-ppc32.h
+++ b/arch/powerpc/include/asm/pgtable-ppc32.h
@@ -429,7 +429,8 @@ extern int icache_44x_need_flush;
#define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE()
#endif
-#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY | \
+ _PAGE_SPECIAL)
#define PAGE_PROT_BITS (_PAGE_GUARDED | _PAGE_COHERENT | _PAGE_NO_CACHE | \
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c
index 5af4e9b2dbe2..ada06924a423 100644
--- a/arch/powerpc/kernel/align.c
+++ b/arch/powerpc/kernel/align.c
@@ -646,11 +646,16 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg,
unsigned int areg, struct pt_regs *regs,
unsigned int flags, unsigned int length)
{
- char *ptr = (char *) &current->thread.TS_FPR(reg);
+ char *ptr;
int ret = 0;
flush_vsx_to_thread(current);
+ if (reg < 32)
+ ptr = (char *) &current->thread.TS_FPR(reg);
+ else
+ ptr = (char *) &current->thread.vr[reg - 32];
+
if (flags & ST)
ret = __copy_to_user(addr, ptr, length);
else {
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 2822c8ccfaaf..5f81256287f5 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -125,6 +125,10 @@ static void kvmppc_free_vcpus(struct kvm *kvm)
}
}
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvmppc_free_vcpus(kvm);
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c
index 7393bd76d698..5ac08b8ab654 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -19,6 +19,7 @@
#include <linux/notifier.h>
#include <linux/lmb.h>
#include <linux/of.h>
+#include <linux/pfn.h>
#include <asm/sparsemem.h>
#include <asm/prom.h>
#include <asm/system.h>
@@ -882,7 +883,7 @@ static void mark_reserved_regions_for_nid(int nid)
unsigned long physbase = lmb.reserved.region[i].base;
unsigned long size = lmb.reserved.region[i].size;
unsigned long start_pfn = physbase >> PAGE_SHIFT;
- unsigned long end_pfn = ((physbase + size) >> PAGE_SHIFT);
+ unsigned long end_pfn = PFN_UP(physbase + size);
struct node_active_region node_ar;
unsigned long node_end_pfn = node->node_start_pfn +
node->node_spanned_pages;
@@ -908,7 +909,7 @@ static void mark_reserved_regions_for_nid(int nid)
*/
if (end_pfn > node_ar.end_pfn)
reserve_size = (node_ar.end_pfn << PAGE_SHIFT)
- - (start_pfn << PAGE_SHIFT);
+ - physbase;
/*
* Only worry about *this* node, others may not
* yet have valid NODE_DATA().
diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c
index 67de6bf3db3d..d281cc0bca71 100644
--- a/arch/powerpc/platforms/ps3/mm.c
+++ b/arch/powerpc/platforms/ps3/mm.c
@@ -328,7 +328,7 @@ static int __init ps3_mm_add_memory(void)
return result;
}
-core_initcall(ps3_mm_add_memory);
+device_initcall(ps3_mm_add_memory);
/*============================================================================*/
/* dma routines */
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h
index 521726430afa..95b0f7db3c69 100644
--- a/arch/s390/include/asm/cputime.h
+++ b/arch/s390/include/asm/cputime.h
@@ -145,7 +145,7 @@ cputime_to_timeval(const cputime_t cputime, struct timeval *value)
value->tv_usec = rp.subreg.even / 4096;
value->tv_sec = rp.subreg.odd;
#else
- value->tv_usec = cputime % 4096000000ULL;
+ value->tv_usec = (cputime % 4096000000ULL) / 4096;
value->tv_sec = cputime / 4096000000ULL;
#endif
}
diff --git a/arch/s390/include/asm/setup.h b/arch/s390/include/asm/setup.h
index 2bd9faeb3919..e8bd6ac22c99 100644
--- a/arch/s390/include/asm/setup.h
+++ b/arch/s390/include/asm/setup.h
@@ -43,6 +43,8 @@ struct mem_chunk {
extern struct mem_chunk memory_chunk[];
extern unsigned long real_memory_size;
+extern int memory_end_set;
+extern unsigned long memory_end;
void detect_memory_layout(struct mem_chunk chunk[]);
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index d825f4950e4e..c5cfb6185eac 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -82,7 +82,9 @@ char elf_platform[ELF_PLATFORM_SIZE];
struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
-static unsigned long __initdata memory_end;
+
+int __initdata memory_end_set;
+unsigned long __initdata memory_end;
/*
* This is set up by the setup-routine at boot-time
@@ -281,6 +283,7 @@ void (*pm_power_off)(void) = machine_power_off;
static int __init early_parse_mem(char *p)
{
memory_end = memparse(p, &p);
+ memory_end_set = 1;
return 0;
}
early_param("mem", early_parse_mem);
@@ -508,8 +511,10 @@ static void __init setup_memory_end(void)
int i;
#if defined(CONFIG_ZFCPDUMP) || defined(CONFIG_ZFCPDUMP_MODULE)
- if (ipl_info.type == IPL_TYPE_FCP_DUMP)
+ if (ipl_info.type == IPL_TYPE_FCP_DUMP) {
memory_end = ZFCPDUMP_HSA_SIZE;
+ memory_end_set = 1;
+ }
#endif
memory_size = 0;
memory_end &= PAGE_MASK;
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index be8497186b96..0d33893e1e89 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -212,6 +212,10 @@ static void kvm_free_vcpus(struct kvm *kvm)
}
}
+void kvm_arch_sync_events(struct kvm *kvm)
+{
+}
+
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvm_free_vcpus(kvm);
diff --git a/arch/um/drivers/vde_user.c b/arch/um/drivers/vde_user.c
index 56533db25343..c5c43253e6ce 100644
--- a/arch/um/drivers/vde_user.c
+++ b/arch/um/drivers/vde_user.c
@@ -78,7 +78,7 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
{
struct vde_open_args *args;
- vpri->args = kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
+ vpri->args = uml_kmalloc(sizeof(struct vde_open_args), UM_GFP_KERNEL);
if (vpri->args == NULL) {
printk(UM_KERN_ERR "vde_init_libstuff - vde_open_args "
"allocation failed");
@@ -91,8 +91,8 @@ void vde_init_libstuff(struct vde_data *vpri, struct vde_init *init)
args->group = init->group;
args->mode = init->mode ? init->mode : 0700;
- args->port ? printk(UM_KERN_INFO "port %d", args->port) :
- printk(UM_KERN_INFO "undefined port");
+ args->port ? printk("port %d", args->port) :
+ printk("undefined port");
}
int vde_user_read(void *conn, void *buf, int len)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 1042d69b267d..5e2919c0ff92 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -235,6 +235,20 @@ config SMP
If you don't know what to do here, say N.
+config X86_X2APIC
+ bool "Support x2apic"
+ depends on X86_LOCAL_APIC && X86_64
+ ---help---
+ This enables x2apic support on CPUs that have this feature.
+
+ This allows 32-bit apic IDs (so it can support very large systems),
+ and accesses the local apic via MSRs not via mmio.
+
+ ( On certain CPU models you may need to enable INTR_REMAP too,
+ to get functional x2apic mode. )
+
+ If you don't know what to do here, say N.
+
config SPARSE_IRQ
bool "Support sparse irq numbering"
depends on PCI_MSI || HT_IRQ
@@ -271,6 +285,7 @@ config X86_BIGSMP
---help---
This option is needed for the systems that have more than 8 CPUs
+if X86_32
config X86_EXTENDED_PLATFORM
bool "Support for extended (non-PC) x86 platforms"
default y
@@ -279,12 +294,36 @@ config X86_EXTENDED_PLATFORM
standard PC platforms. (which covers the vast majority of
systems out there.)
- If you enable this option then you'll be able to select a number
- of non-PC x86 platforms.
+ If you enable this option then you'll be able to select support
+ for the following (non-PC) 32 bit x86 platforms:
+ AMD Elan
+ NUMAQ (IBM/Sequent)
+ RDC R-321x SoC
+ SGI 320/540 (Visual Workstation)
+ Summit/EXA (IBM x440)
+ Unisys ES7000 IA32 series
If you have one of these systems, or if you want to build a
generic distribution kernel, say Y here - otherwise say N.
+endif
+if X86_64
+config X86_EXTENDED_PLATFORM
+ bool "Support for extended (non-PC) x86 platforms"
+ default y
+ ---help---
+ If you disable this option then the kernel will only support
+ standard PC platforms. (which covers the vast majority of
+ systems out there.)
+
+ If you enable this option then you'll be able to select support
+ for the following (non-PC) 64 bit x86 platforms:
+ ScaleMP vSMP
+ SGI Ultraviolet
+
+ If you have one of these systems, or if you want to build a
+ generic distribution kernel, say Y here - otherwise say N.
+endif
# This is an alphabetically sorted list of 64 bit extended platforms
# Please maintain the alphabetic order if and when there are additions
@@ -302,6 +341,7 @@ config X86_UV
bool "SGI Ultraviolet"
depends on X86_64
depends on X86_EXTENDED_PLATFORM
+ select X86_X2APIC
---help---
This option is needed in order to support SGI Ultraviolet systems.
If you don't have one of these, you should say N here.
@@ -382,19 +422,6 @@ config X86_ES7000
Support for Unisys ES7000 systems. Say 'Y' here if this kernel is
supposed to run on an IA32-based Unisys ES7000 system.
-config X86_VOYAGER
- bool "Voyager (NCR)"
- depends on SMP && !PCI && BROKEN
- depends on X86_32_NON_STANDARD
- ---help---
- Voyager is an MCA-based 32-way capable SMP architecture proprietary
- to NCR Corp. Machine classes 345x/35xx/4100/51xx are Voyager-based.
-
- *** WARNING ***
-
- If you do not specifically know you have a Voyager based machine,
- say N here, otherwise the kernel you build will not be bootable.
-
config SCHED_OMIT_FRAME_POINTER
def_bool y
prompt "Single-depth WCHAN output"
@@ -1828,6 +1855,7 @@ config DMAR_FLOPPY_WA
config INTR_REMAP
bool "Support for Interrupt Remapping (EXPERIMENTAL)"
depends on X86_64 && X86_IO_APIC && PCI_MSI && ACPI && EXPERIMENTAL
+ select X86_X2APIC
---help---
Supports Interrupt remapping for IO-APIC and MSI devices.
To use x2apic mode in the CPU's which support x2APIC enhancements or
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index ba4781b93890..fdb45df608b6 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -175,28 +175,8 @@ config IOMMU_LEAK
Add a simple leak tracer to the IOMMU code. This is useful when you
are debugging a buggy device driver that leaks IOMMU mappings.
-config MMIOTRACE
- bool "Memory mapped IO tracing"
- depends on DEBUG_KERNEL && PCI
- select TRACING
- help
- Mmiotrace traces Memory Mapped I/O access and is meant for
- debugging and reverse engineering. It is called from the ioremap
- implementation and works via page faults. Tracing is disabled by
- default and can be enabled at run-time.
-
- See Documentation/tracers/mmiotrace.txt.
- If you are not helping to develop drivers, say N.
-
-config MMIOTRACE_TEST
- tristate "Test module for mmiotrace"
- depends on MMIOTRACE && m
- help
- This is a dumb module for testing mmiotrace. It is very dangerous
- as it will write garbage to IO memory starting at a given address.
- However, it should be safe to use on e.g. unused portion of VRAM.
-
- Say N, unless you absolutely know what you are doing.
+config HAVE_MMIOTRACE_SUPPORT
+ def_bool y
#
# IO delay types:
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index cd48c7210016..c70eff69a1fb 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -32,7 +32,6 @@ setup-y += a20.o cmdline.o copy.o cpu.o cpucheck.o edd.o
setup-y += header.o main.o mca.o memory.o pm.o pmjump.o
setup-y += printf.o string.o tty.o video.o video-mode.o version.o
setup-$(CONFIG_X86_APM_BOOT) += apm.o
-setup-$(CONFIG_X86_VOYAGER) += voyager.o
# The link order of the video-*.o modules can matter. In particular,
# video-vga.o *must* be listed first, followed by video-vesa.o.
diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c
index fba8e9c6a504..7c19ce8c2442 100644
--- a/arch/x86/boot/a20.c
+++ b/arch/x86/boot/a20.c
@@ -126,11 +126,6 @@ static void enable_a20_fast(void)
int enable_a20(void)
{
-#ifdef CONFIG_X86_VOYAGER
- /* On Voyager, a20_test() is unsafe? */
- enable_a20_kbc();
- return 0;
-#else
int loops = A20_ENABLE_LOOPS;
int kbc_err;
@@ -164,5 +159,4 @@ int enable_a20(void)
}
return -1;
-#endif
}
diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h
index cc0ef13fba7a..7b2692e897e5 100644
--- a/arch/x86/boot/boot.h
+++ b/arch/x86/boot/boot.h
@@ -302,9 +302,6 @@ void probe_cards(int unsafe);
/* video-vesa.c */
void vesa_store_edid(void);
-/* voyager.c */
-int query_voyager(void);
-
#endif /* __ASSEMBLY__ */
#endif /* BOOT_BOOT_H */
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 9f20d3794060..3a8a866fb2e2 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -25,7 +25,7 @@
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/boot.h>
#include <asm/asm-offsets.h>
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index ba9229ba7f0d..ed4a82948002 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -26,8 +26,8 @@
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <asm/pgtable_types.h>
+#include <asm/page_types.h>
#include <asm/boot.h>
#include <asm/msr.h>
#include <asm/processor-flags.h>
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index b993062e9a5f..7ccff4884a23 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -19,7 +19,7 @@
#include <linux/utsrelease.h>
#include <asm/boot.h>
#include <asm/e820.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/setup.h>
#include "boot.h"
#include "offsets.h"
diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c
index 197421db1af1..58f0415d3ae0 100644
--- a/arch/x86/boot/main.c
+++ b/arch/x86/boot/main.c
@@ -149,11 +149,6 @@ void main(void)
/* Query MCA information */
query_mca();
- /* Voyager */
-#ifdef CONFIG_X86_VOYAGER
- query_voyager();
-#endif
-
/* Query Intel SpeedStep (IST) information */
query_ist();
diff --git a/arch/x86/boot/voyager.c b/arch/x86/boot/voyager.c
deleted file mode 100644
index 433909d61e5c..000000000000
--- a/arch/x86/boot/voyager.c
+++ /dev/null
@@ -1,40 +0,0 @@
-/* -*- linux-c -*- ------------------------------------------------------- *
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- * Copyright 2007 rPath, Inc. - All Rights Reserved
- *
- * This file is part of the Linux kernel, and is made available under
- * the terms of the GNU General Public License version 2.
- *
- * ----------------------------------------------------------------------- */
-
-/*
- * Get the Voyager config information
- */
-
-#include "boot.h"
-
-int query_voyager(void)
-{
- u8 err;
- u16 es, di;
- /* Abuse the apm_bios_info area for this */
- u8 *data_ptr = (u8 *)&boot_params.apm_bios_info;
-
- data_ptr[0] = 0xff; /* Flag on config not found(?) */
-
- asm("pushw %%es ; "
- "int $0x15 ; "
- "setc %0 ; "
- "movw %%es, %1 ; "
- "popw %%es"
- : "=q" (err), "=r" (es), "=D" (di)
- : "a" (0xffc0));
-
- if (err)
- return -1; /* Not Voyager */
-
- set_fs(es);
- copy_from_fs(data_ptr, di, 7); /* Table is 7 bytes apparently */
- return 0;
-}
diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig
index 096dd5359cd9..5c023f6f652c 100644
--- a/arch/x86/configs/i386_defconfig
+++ b/arch/x86/configs/i386_defconfig
@@ -197,7 +197,6 @@ CONFIG_SPARSE_IRQ=y
CONFIG_X86_FIND_SMP_CONFIG=y
CONFIG_X86_MPPARSE=y
# CONFIG_X86_ELAN is not set
-# CONFIG_X86_VOYAGER is not set
# CONFIG_X86_GENERICARCH is not set
# CONFIG_X86_VSMP is not set
# CONFIG_X86_RDC321X is not set
diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig
index 2efb5d5063ff..4157cc4a2bde 100644
--- a/arch/x86/configs/x86_64_defconfig
+++ b/arch/x86/configs/x86_64_defconfig
@@ -199,7 +199,6 @@ CONFIG_SPARSE_IRQ=y
CONFIG_X86_FIND_SMP_CONFIG=y
CONFIG_X86_MPPARSE=y
# CONFIG_X86_ELAN is not set
-# CONFIG_X86_VOYAGER is not set
# CONFIG_X86_GENERICARCH is not set
# CONFIG_X86_VSMP is not set
CONFIG_SCHED_OMIT_FRAME_POINTER=y
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index dd77ac0cac46..588a7aa937e1 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -33,8 +33,6 @@
#include <asm/sigframe.h>
#include <asm/sys_ia32.h>
-#define DEBUG_SIG 0
-
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
@@ -190,42 +188,47 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
/*
* Do a signal return; undo the signal stack.
*/
+#define loadsegment_gs(v) load_gs_index(v)
+#define loadsegment_fs(v) loadsegment(fs, v)
+#define loadsegment_ds(v) loadsegment(ds, v)
+#define loadsegment_es(v) loadsegment(es, v)
+
+#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
+#define set_user_seg(seg, v) loadsegment_##seg(v)
+
#define COPY(x) { \
get_user_ex(regs->x, &sc->x); \
}
-#define COPY_SEG_CPL3(seg) { \
- unsigned short tmp; \
- get_user_ex(tmp, &sc->seg); \
- regs->seg = tmp | 3; \
-}
+#define GET_SEG(seg) ({ \
+ unsigned short tmp; \
+ get_user_ex(tmp, &sc->seg); \
+ tmp; \
+})
+
+#define COPY_SEG_CPL3(seg) do { \
+ regs->seg = GET_SEG(seg) | 3; \
+} while (0)
#define RELOAD_SEG(seg) { \
- unsigned int cur, pre; \
- get_user_ex(pre, &sc->seg); \
- savesegment(seg, cur); \
+ unsigned int pre = GET_SEG(seg); \
+ unsigned int cur = get_user_seg(seg); \
pre |= 3; \
if (pre != cur) \
- loadsegment(seg, pre); \
+ set_user_seg(seg, pre); \
}
static int ia32_restore_sigcontext(struct pt_regs *regs,
struct sigcontext_ia32 __user *sc,
unsigned int *pax)
{
- unsigned int tmpflags, gs, oldgs, err = 0;
+ unsigned int tmpflags, err = 0;
void __user *buf;
u32 tmp;
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
-#if DEBUG_SIG
- printk(KERN_DEBUG "SIG restore_sigcontext: "
- "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
- sc, sc->err, sc->ip, sc->cs, sc->flags);
-#endif
-
get_user_try {
/*
* Reload fs and gs if they have changed in the signal
@@ -233,12 +236,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
* the handler, but does not clobber them at least in the
* normal case.
*/
- get_user_ex(gs, &sc->gs);
- gs |= 3;
- savesegment(gs, oldgs);
- if (gs != oldgs)
- load_gs_index(gs);
-
+ RELOAD_SEG(gs);
RELOAD_SEG(fs);
RELOAD_SEG(ds);
RELOAD_SEG(es);
@@ -337,17 +335,13 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
void __user *fpstate,
struct pt_regs *regs, unsigned int mask)
{
- int tmp, err = 0;
+ int err = 0;
put_user_try {
- savesegment(gs, tmp);
- put_user_ex(tmp, (unsigned int __user *)&sc->gs);
- savesegment(fs, tmp);
- put_user_ex(tmp, (unsigned int __user *)&sc->fs);
- savesegment(ds, tmp);
- put_user_ex(tmp, (unsigned int __user *)&sc->ds);
- savesegment(es, tmp);
- put_user_ex(tmp, (unsigned int __user *)&sc->es);
+ put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
+ put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
+ put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
+ put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
put_user_ex(regs->di, &sc->di);
put_user_ex(regs->si, &sc->si);
@@ -488,11 +482,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
regs->cs = __USER32_CS;
regs->ss = __USER32_DS;
-#if DEBUG_SIG
- printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
- current->comm, current->pid, frame, regs->ip, frame->pretcode);
-#endif
-
return 0;
}
@@ -574,10 +563,5 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->cs = __USER32_CS;
regs->ss = __USER32_DS;
-#if DEBUG_SIG
- printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
- current->comm, current->pid, frame, regs->ip, frame->pretcode);
-#endif
-
return 0;
}
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index fba49f66228f..a6208dc74633 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -1,15 +1,18 @@
#ifndef _ASM_X86_APIC_H
#define _ASM_X86_APIC_H
-#include <linux/pm.h>
+#include <linux/cpumask.h>
#include <linux/delay.h>
+#include <linux/pm.h>
#include <asm/alternative.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
+#include <asm/cpufeature.h>
#include <asm/processor.h>
+#include <asm/apicdef.h>
+#include <asm/atomic.h>
+#include <asm/fixmap.h>
+#include <asm/mpspec.h>
#include <asm/system.h>
-#include <asm/cpufeature.h>
#include <asm/msr.h>
#define ARCH_APICTIMER_STOPS_ON_C3 1
@@ -92,6 +95,12 @@ static inline u32 native_apic_mem_read(u32 reg)
return *((volatile u32 *)(APIC_BASE + reg));
}
+extern void native_apic_wait_icr_idle(void);
+extern u32 native_safe_apic_wait_icr_idle(void);
+extern void native_apic_icr_write(u32 low, u32 id);
+extern u64 native_apic_icr_read(void);
+
+#ifdef CONFIG_X86_X2APIC
static inline void native_apic_msr_write(u32 reg, u32 v)
{
if (reg == APIC_DFR || reg == APIC_ID || reg == APIC_LDR ||
@@ -112,8 +121,32 @@ static inline u32 native_apic_msr_read(u32 reg)
return low;
}
-#ifndef CONFIG_X86_32
-extern int x2apic;
+static inline void native_x2apic_wait_icr_idle(void)
+{
+ /* no need to wait for icr idle in x2apic */
+ return;
+}
+
+static inline u32 native_safe_x2apic_wait_icr_idle(void)
+{
+ /* no need to wait for icr idle in x2apic */
+ return 0;
+}
+
+static inline void native_x2apic_icr_write(u32 low, u32 id)
+{
+ wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
+}
+
+static inline u64 native_x2apic_icr_read(void)
+{
+ unsigned long val;
+
+ rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val);
+ return val;
+}
+
+extern int x2apic, x2apic_phys;
extern void check_x2apic(void);
extern void enable_x2apic(void);
extern void enable_IR_x2apic(void);
@@ -131,53 +164,24 @@ static inline int x2apic_enabled(void)
return 0;
}
#else
-#define x2apic_enabled() 0
-#endif
-
-struct apic_ops {
- u32 (*read)(u32 reg);
- void (*write)(u32 reg, u32 v);
- u64 (*icr_read)(void);
- void (*icr_write)(u32 low, u32 high);
- void (*wait_icr_idle)(void);
- u32 (*safe_wait_icr_idle)(void);
-};
-
-extern struct apic_ops *apic_ops;
-
-static inline u32 apic_read(u32 reg)
+static inline void check_x2apic(void)
{
- return apic_ops->read(reg);
}
-
-static inline void apic_write(u32 reg, u32 val)
+static inline void enable_x2apic(void)
{
- apic_ops->write(reg, val);
}
-
-static inline u64 apic_icr_read(void)
+static inline void enable_IR_x2apic(void)
{
- return apic_ops->icr_read();
}
-
-static inline void apic_icr_write(u32 low, u32 high)
-{
- apic_ops->icr_write(low, high);
-}
-
-static inline void apic_wait_icr_idle(void)
-{
- apic_ops->wait_icr_idle();
-}
-
-static inline u32 safe_apic_wait_icr_idle(void)
+static inline int x2apic_enabled(void)
{
- return apic_ops->safe_wait_icr_idle();
+ return 0;
}
+#endif
extern int get_physical_broadcast(void);
-#ifdef CONFIG_X86_64
+#ifdef CONFIG_X86_X2APIC
static inline void ack_x2APIC_irq(void)
{
/* Docs say use 0 for future compatibility */
@@ -185,18 +189,6 @@ static inline void ack_x2APIC_irq(void)
}
#endif
-
-static inline void ack_APIC_irq(void)
-{
- /*
- * ack_APIC_irq() actually gets compiled as a single instruction
- * ... yummie.
- */
-
- /* Docs say use 0 for future compatibility */
- apic_write(APIC_EOI, 0);
-}
-
extern int lapic_get_maxlvt(void);
extern void clear_local_APIC(void);
extern void connect_bsp_APIC(void);
@@ -244,7 +236,138 @@ static inline void disable_local_APIC(void) { }
#define SET_APIC_ID(x) (apic->set_apic_id(x))
#else
-#ifdef CONFIG_X86_LOCAL_APIC
+#endif
+
+/*
+ * Copyright 2004 James Cleverdon, IBM.
+ * Subject to the GNU Public License, v.2
+ *
+ * Generic APIC sub-arch data struct.
+ *
+ * Hacked for x86-64 by James Cleverdon from i386 architecture code by
+ * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
+ * James Cleverdon.
+ */
+struct apic {
+ char *name;
+
+ int (*probe)(void);
+ int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
+ int (*apic_id_registered)(void);
+
+ u32 irq_delivery_mode;
+ u32 irq_dest_mode;
+
+ const struct cpumask *(*target_cpus)(void);
+
+ int disable_esr;
+
+ int dest_logical;
+ unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid);
+ unsigned long (*check_apicid_present)(int apicid);
+
+ void (*vector_allocation_domain)(int cpu, struct cpumask *retmask);
+ void (*init_apic_ldr)(void);
+
+ physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map);
+
+ void (*setup_apic_routing)(void);
+ int (*multi_timer_check)(int apic, int irq);
+ int (*apicid_to_node)(int logical_apicid);
+ int (*cpu_to_logical_apicid)(int cpu);
+ int (*cpu_present_to_apicid)(int mps_cpu);
+ physid_mask_t (*apicid_to_cpu_present)(int phys_apicid);
+ void (*setup_portio_remap)(void);
+ int (*check_phys_apicid_present)(int boot_cpu_physical_apicid);
+ void (*enable_apic_mode)(void);
+ int (*phys_pkg_id)(int cpuid_apic, int index_msb);
+
+ /*
+ * When one of the next two hooks returns 1 the apic
+ * is switched to this. Essentially they are additional
+ * probe functions:
+ */
+ int (*mps_oem_check)(struct mpc_table *mpc, char *oem, char *productid);
+
+ unsigned int (*get_apic_id)(unsigned long x);
+ unsigned long (*set_apic_id)(unsigned int id);
+ unsigned long apic_id_mask;
+
+ unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask);
+ unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask,
+ const struct cpumask *andmask);
+
+ /* ipi */
+ void (*send_IPI_mask)(const struct cpumask *mask, int vector);
+ void (*send_IPI_mask_allbutself)(const struct cpumask *mask,
+ int vector);
+ void (*send_IPI_allbutself)(int vector);
+ void (*send_IPI_all)(int vector);
+ void (*send_IPI_self)(int vector);
+
+ /* wakeup_secondary_cpu */
+ int (*wakeup_cpu)(int apicid, unsigned long start_eip);
+
+ int trampoline_phys_low;
+ int trampoline_phys_high;
+
+ void (*wait_for_init_deassert)(atomic_t *deassert);
+ void (*smp_callin_clear_local_apic)(void);
+ void (*inquire_remote_apic)(int apicid);
+
+ /* apic ops */
+ u32 (*read)(u32 reg);
+ void (*write)(u32 reg, u32 v);
+ u64 (*icr_read)(void);
+ void (*icr_write)(u32 low, u32 high);
+ void (*wait_icr_idle)(void);
+ u32 (*safe_wait_icr_idle)(void);
+};
+
+extern struct apic *apic;
+
+static inline u32 apic_read(u32 reg)
+{
+ return apic->read(reg);
+}
+
+static inline void apic_write(u32 reg, u32 val)
+{
+ apic->write(reg, val);
+}
+
+static inline u64 apic_icr_read(void)
+{
+ return apic->icr_read();
+}
+
+static inline void apic_icr_write(u32 low, u32 high)
+{
+ apic->icr_write(low, high);
+}
+
+static inline void apic_wait_icr_idle(void)
+{
+ apic->wait_icr_idle();
+}
+
+static inline u32 safe_apic_wait_icr_idle(void)
+{
+ return apic->safe_wait_icr_idle();
+}
+
+
+static inline void ack_APIC_irq(void)
+{
+ /*
+ * ack_APIC_irq() actually gets compiled as a single instruction
+ * ... yummie.
+ */
+
+ /* Docs say use 0 for future compatibility */
+ apic_write(APIC_EOI, 0);
+}
+
static inline unsigned default_get_apic_id(unsigned long x)
{
unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
@@ -254,8 +377,171 @@ static inline unsigned default_get_apic_id(unsigned long x)
else
return (x >> 24) & 0x0F;
}
+
+/*
+ * Warm reset vector default position:
+ */
+#define DEFAULT_TRAMPOLINE_PHYS_LOW 0x467
+#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469
+
+#ifdef CONFIG_X86_32
+extern void es7000_update_apic_to_cluster(void);
+#else
+extern struct apic apic_flat;
+extern struct apic apic_physflat;
+extern struct apic apic_x2apic_cluster;
+extern struct apic apic_x2apic_phys;
+extern int default_acpi_madt_oem_check(char *, char *);
+
+extern void apic_send_IPI_self(int vector);
+
+extern struct apic apic_x2apic_uv_x;
+DECLARE_PER_CPU(int, x2apic_extra_bits);
+
+extern int default_cpu_present_to_apicid(int mps_cpu);
+extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid);
+#endif
+
+static inline void default_wait_for_init_deassert(atomic_t *deassert)
+{
+ while (!atomic_read(deassert))
+ cpu_relax();
+ return;
+}
+
+extern void generic_bigsmp_probe(void);
+
+
+#ifdef CONFIG_X86_LOCAL_APIC
+
+#include <asm/smp.h>
+
+#define APIC_DFR_VALUE (APIC_DFR_FLAT)
+
+static inline const struct cpumask *default_target_cpus(void)
+{
+#ifdef CONFIG_SMP
+ return cpu_online_mask;
+#else
+ return cpumask_of(0);
#endif
+}
+
+DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
+
+
+static inline unsigned int read_apic_id(void)
+{
+ unsigned int reg;
+
+ reg = apic_read(APIC_ID);
+
+ return apic->get_apic_id(reg);
+}
+
+extern void default_setup_apic_routing(void);
+
+#ifdef CONFIG_X86_32
+/*
+ * Set up the logical destination ID.
+ *
+ * Intel recommends to set DFR, LDR and TPR before enabling
+ * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
+ * document number 292116). So here it goes...
+ */
+extern void default_init_apic_ldr(void);
+
+static inline int default_apic_id_registered(void)
+{
+ return physid_isset(read_apic_id(), phys_cpu_present_map);
+}
+
+static inline unsigned int
+default_cpu_mask_to_apicid(const struct cpumask *cpumask)
+{
+ return cpumask_bits(cpumask)[0];
+}
+
+static inline unsigned int
+default_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+ const struct cpumask *andmask)
+{
+ unsigned long mask1 = cpumask_bits(cpumask)[0];
+ unsigned long mask2 = cpumask_bits(andmask)[0];
+ unsigned long mask3 = cpumask_bits(cpu_online_mask)[0];
+
+ return (unsigned int)(mask1 & mask2 & mask3);
+}
+
+static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
+{
+ return cpuid_apic >> index_msb;
+}
+
+extern int default_apicid_to_node(int logical_apicid);
+
+#endif
+
+static inline unsigned long default_check_apicid_used(physid_mask_t bitmap, int apicid)
+{
+ return physid_isset(apicid, bitmap);
+}
+
+static inline unsigned long default_check_apicid_present(int bit)
+{
+ return physid_isset(bit, phys_cpu_present_map);
+}
+
+static inline physid_mask_t default_ioapic_phys_id_map(physid_mask_t phys_map)
+{
+ return phys_map;
+}
+
+/* Mapping from cpu number to logical apicid */
+static inline int default_cpu_to_logical_apicid(int cpu)
+{
+ return 1 << cpu;
+}
+
+static inline int __default_cpu_present_to_apicid(int mps_cpu)
+{
+ if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu))
+ return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
+ else
+ return BAD_APICID;
+}
+
+static inline int
+__default_check_phys_apicid_present(int boot_cpu_physical_apicid)
+{
+ return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map);
+}
+
+#ifdef CONFIG_X86_32
+static inline int default_cpu_present_to_apicid(int mps_cpu)
+{
+ return __default_cpu_present_to_apicid(mps_cpu);
+}
+
+static inline int
+default_check_phys_apicid_present(int boot_cpu_physical_apicid)
+{
+ return __default_check_phys_apicid_present(boot_cpu_physical_apicid);
+}
+#else
+extern int default_cpu_present_to_apicid(int mps_cpu);
+extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid);
+#endif
+
+static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid)
+{
+ return physid_mask_of_physid(phys_apicid);
+}
+
+#endif /* CONFIG_X86_LOCAL_APIC */
+#ifdef CONFIG_X86_32
+extern u8 cpu_2_logical_apicid[NR_CPUS];
#endif
#endif /* _ASM_X86_APIC_H */
diff --git a/arch/x86/include/asm/arch_hooks.h b/arch/x86/include/asm/arch_hooks.h
deleted file mode 100644
index cbd4957838a6..000000000000
--- a/arch/x86/include/asm/arch_hooks.h
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef _ASM_X86_ARCH_HOOKS_H
-#define _ASM_X86_ARCH_HOOKS_H
-
-#include <linux/interrupt.h>
-
-/*
- * linux/include/asm/arch_hooks.h
- *
- * define the architecture specific hooks
- */
-
-/* these aren't arch hooks, they are generic routines
- * that can be used by the hooks */
-extern void init_ISA_irqs(void);
-extern irqreturn_t timer_interrupt(int irq, void *dev_id);
-
-/* these are the defined hooks */
-extern void intr_init_hook(void);
-extern void pre_intr_init_hook(void);
-extern void pre_setup_arch_hook(void);
-extern void trap_init_hook(void);
-extern void pre_time_init_hook(void);
-extern void time_init_hook(void);
-extern void mca_nmi_hook(void);
-
-#endif /* _ASM_X86_ARCH_HOOKS_H */
diff --git a/arch/x86/include/asm/genapic.h b/arch/x86/include/asm/genapic.h
index 273b99452ae0..4b8b98fa7f25 100644
--- a/arch/x86/include/asm/genapic.h
+++ b/arch/x86/include/asm/genapic.h
@@ -1,263 +1 @@
-#ifndef _ASM_X86_GENAPIC_H
-#define _ASM_X86_GENAPIC_H
-
-#include <linux/cpumask.h>
-
-#include <asm/mpspec.h>
-#include <asm/atomic.h>
-
-/*
- * Copyright 2004 James Cleverdon, IBM.
- * Subject to the GNU Public License, v.2
- *
- * Generic APIC sub-arch data struct.
- *
- * Hacked for x86-64 by James Cleverdon from i386 architecture code by
- * Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
- * James Cleverdon.
- */
-struct genapic {
- char *name;
-
- int (*probe)(void);
- int (*acpi_madt_oem_check)(char *oem_id, char *oem_table_id);
- int (*apic_id_registered)(void);
-
- u32 irq_delivery_mode;
- u32 irq_dest_mode;
-
- const struct cpumask *(*target_cpus)(void);
-
- int disable_esr;
-
- int dest_logical;
- unsigned long (*check_apicid_used)(physid_mask_t bitmap, int apicid);
- unsigned long (*check_apicid_present)(int apicid);
-
- void (*vector_allocation_domain)(int cpu, struct cpumask *retmask);
- void (*init_apic_ldr)(void);
-
- physid_mask_t (*ioapic_phys_id_map)(physid_mask_t map);
-
- void (*setup_apic_routing)(void);
- int (*multi_timer_check)(int apic, int irq);
- int (*apicid_to_node)(int logical_apicid);
- int (*cpu_to_logical_apicid)(int cpu);
- int (*cpu_present_to_apicid)(int mps_cpu);
- physid_mask_t (*apicid_to_cpu_present)(int phys_apicid);
- void (*setup_portio_remap)(void);
- int (*check_phys_apicid_present)(int boot_cpu_physical_apicid);
- void (*enable_apic_mode)(void);
- int (*phys_pkg_id)(int cpuid_apic, int index_msb);
-
- /*
- * When one of the next two hooks returns 1 the genapic
- * is switched to this. Essentially they are additional
- * probe functions:
- */
- int (*mps_oem_check)(struct mpc_table *mpc, char *oem, char *productid);
-
- unsigned int (*get_apic_id)(unsigned long x);
- unsigned long (*set_apic_id)(unsigned int id);
- unsigned long apic_id_mask;
-
- unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask);
- unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask,
- const struct cpumask *andmask);
-
- /* ipi */
- void (*send_IPI_mask)(const struct cpumask *mask, int vector);
- void (*send_IPI_mask_allbutself)(const struct cpumask *mask,
- int vector);
- void (*send_IPI_allbutself)(int vector);
- void (*send_IPI_all)(int vector);
- void (*send_IPI_self)(int vector);
-
- /* wakeup_secondary_cpu */
- int (*wakeup_cpu)(int apicid, unsigned long start_eip);
-
- int trampoline_phys_low;
- int trampoline_phys_high;
-
- void (*wait_for_init_deassert)(atomic_t *deassert);
- void (*smp_callin_clear_local_apic)(void);
- void (*store_NMI_vector)(unsigned short *high, unsigned short *low);
- void (*inquire_remote_apic)(int apicid);
-};
-
-extern struct genapic *apic;
-
-/*
- * Warm reset vector default position:
- */
-#define DEFAULT_TRAMPOLINE_PHYS_LOW 0x467
-#define DEFAULT_TRAMPOLINE_PHYS_HIGH 0x469
-
-#ifdef CONFIG_X86_32
-extern void es7000_update_genapic_to_cluster(void);
-#else
-extern struct genapic apic_flat;
-extern struct genapic apic_physflat;
-extern struct genapic apic_x2apic_cluster;
-extern struct genapic apic_x2apic_phys;
-extern int default_acpi_madt_oem_check(char *, char *);
-
-extern void apic_send_IPI_self(int vector);
-
-extern struct genapic apic_x2apic_uv_x;
-DECLARE_PER_CPU(int, x2apic_extra_bits);
-
-extern void default_setup_apic_routing(void);
-
-extern int default_cpu_present_to_apicid(int mps_cpu);
-extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid);
-#endif
-
-static inline void default_wait_for_init_deassert(atomic_t *deassert)
-{
- while (!atomic_read(deassert))
- cpu_relax();
- return;
-}
-
-extern void generic_bigsmp_probe(void);
-
-
-#ifdef CONFIG_X86_LOCAL_APIC
-
-#include <asm/smp.h>
-
-#define APIC_DFR_VALUE (APIC_DFR_FLAT)
-
-static inline const struct cpumask *default_target_cpus(void)
-{
-#ifdef CONFIG_SMP
- return cpu_online_mask;
-#else
- return cpumask_of(0);
-#endif
-}
-
-DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
-
-
-static inline unsigned int read_apic_id(void)
-{
- unsigned int reg;
-
- reg = apic_read(APIC_ID);
-
- return apic->get_apic_id(reg);
-}
-
-#ifdef CONFIG_X86_64
-extern void default_setup_apic_routing(void);
-#else
-
-/*
- * Set up the logical destination ID.
- *
- * Intel recommends to set DFR, LDR and TPR before enabling
- * an APIC. See e.g. "AP-388 82489DX User's Manual" (Intel
- * document number 292116). So here it goes...
- */
-extern void default_init_apic_ldr(void);
-
-static inline int default_apic_id_registered(void)
-{
- return physid_isset(read_apic_id(), phys_cpu_present_map);
-}
-
-static inline unsigned int
-default_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
- return cpumask_bits(cpumask)[0];
-}
-
-static inline unsigned int
-default_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
- const struct cpumask *andmask)
-{
- unsigned long mask1 = cpumask_bits(cpumask)[0];
- unsigned long mask2 = cpumask_bits(andmask)[0];
- unsigned long mask3 = cpumask_bits(cpu_online_mask)[0];
-
- return (unsigned int)(mask1 & mask2 & mask3);
-}
-
-static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
-{
- return cpuid_apic >> index_msb;
-}
-
-static inline void default_setup_apic_routing(void)
-{
-#ifdef CONFIG_X86_IO_APIC
- printk("Enabling APIC mode: %s. Using %d I/O APICs\n",
- "Flat", nr_ioapics);
-#endif
-}
-
-extern int default_apicid_to_node(int logical_apicid);
-
-#endif
-
-static inline unsigned long default_check_apicid_used(physid_mask_t bitmap, int apicid)
-{
- return physid_isset(apicid, bitmap);
-}
-
-static inline unsigned long default_check_apicid_present(int bit)
-{
- return physid_isset(bit, phys_cpu_present_map);
-}
-
-static inline physid_mask_t default_ioapic_phys_id_map(physid_mask_t phys_map)
-{
- return phys_map;
-}
-
-/* Mapping from cpu number to logical apicid */
-static inline int default_cpu_to_logical_apicid(int cpu)
-{
- return 1 << cpu;
-}
-
-static inline int __default_cpu_present_to_apicid(int mps_cpu)
-{
- if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu))
- return (int)per_cpu(x86_bios_cpu_apicid, mps_cpu);
- else
- return BAD_APICID;
-}
-
-static inline int
-__default_check_phys_apicid_present(int boot_cpu_physical_apicid)
-{
- return physid_isset(boot_cpu_physical_apicid, phys_cpu_present_map);
-}
-
-#ifdef CONFIG_X86_32
-static inline int default_cpu_present_to_apicid(int mps_cpu)
-{
- return __default_cpu_present_to_apicid(mps_cpu);
-}
-
-static inline int
-default_check_phys_apicid_present(int boot_cpu_physical_apicid)
-{
- return __default_check_phys_apicid_present(boot_cpu_physical_apicid);
-}
-#else
-extern int default_cpu_present_to_apicid(int mps_cpu);
-extern int default_check_phys_apicid_present(int boot_cpu_physical_apicid);
-#endif
-
-static inline physid_mask_t default_apicid_to_cpu_present(int phys_apicid)
-{
- return physid_mask_of_physid(phys_apicid);
-}
-
-#endif /* CONFIG_X86_LOCAL_APIC */
-
-#endif /* _ASM_X86_GENAPIC_64_H */
+#include <asm/apic.h>
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
index 58d7091eeb1f..1a99e6c092af 100644
--- a/arch/x86/include/asm/i8259.h
+++ b/arch/x86/include/asm/i8259.h
@@ -60,4 +60,8 @@ extern struct irq_chip i8259A_chip;
extern void mask_8259A(void);
extern void unmask_8259A(void);
+#ifdef CONFIG_X86_32
+extern void init_ISA_irqs(void);
+#endif
+
#endif /* _ASM_X86_I8259_H */
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index 4f8e820cf38f..683d0b4c00fc 100644
--- a/arch/x86/include/asm/io.h
+++ b/arch/x86/include/asm/io.h
@@ -124,10 +124,15 @@ static inline void *phys_to_virt(phys_addr_t address)
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
+ * However, we truncate the address to unsigned int to avoid undesirable
+ * promitions in legacy drivers.
*/
-#define isa_virt_to_bus (unsigned long)virt_to_phys
-#define isa_page_to_bus page_to_phys
-#define isa_bus_to_virt phys_to_virt
+static inline unsigned int isa_virt_to_bus(volatile void *address)
+{
+ return (unsigned int)virt_to_phys(address);
+}
+#define isa_page_to_bus(page) ((unsigned int)page_to_phys(page))
+#define isa_bus_to_virt phys_to_virt
/*
* However PCI ones are not necessarily 1:1 and therefore these interfaces
diff --git a/arch/x86/include/asm/ipi.h b/arch/x86/include/asm/ipi.h
index 5f2efc5d9927..0b7228268a63 100644
--- a/arch/x86/include/asm/ipi.h
+++ b/arch/x86/include/asm/ipi.h
@@ -123,8 +123,6 @@ extern void default_send_IPI_mask_sequence_phys(const struct cpumask *mask,
int vector);
extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask,
int vector);
-#include <asm/genapic.h>
-
extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
int vector);
extern void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
index d2e3bf3608af..886c9402ec45 100644
--- a/arch/x86/include/asm/kvm.h
+++ b/arch/x86/include/asm/kvm.h
@@ -9,6 +9,13 @@
#include <linux/types.h>
#include <linux/ioctl.h>
+/* Select x86 specific features in <linux/kvm.h> */
+#define __KVM_HAVE_PIT
+#define __KVM_HAVE_IOAPIC
+#define __KVM_HAVE_DEVICE_ASSIGNMENT
+#define __KVM_HAVE_MSI
+#define __KVM_HAVE_USER_NMI
+
/* Architectural interrupt line count. */
#define KVM_NR_INTERRUPTS 256
diff --git a/arch/x86/include/asm/mach-voyager/do_timer.h b/arch/x86/include/asm/mach-voyager/do_timer.h
deleted file mode 100644
index 9e5a459fd15b..000000000000
--- a/arch/x86/include/asm/mach-voyager/do_timer.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* defines for inline arch setup functions */
-#include <linux/clockchips.h>
-
-#include <asm/voyager.h>
-#include <asm/i8253.h>
-
-/**
- * do_timer_interrupt_hook - hook into timer tick
- *
- * Call the pit clock event handler. see asm/i8253.h
- **/
-static inline void do_timer_interrupt_hook(void)
-{
- global_clock_event->event_handler(global_clock_event);
- voyager_timer_interrupt();
-}
-
diff --git a/arch/x86/include/asm/mach-voyager/entry_arch.h b/arch/x86/include/asm/mach-voyager/entry_arch.h
deleted file mode 100644
index ae52624b5937..000000000000
--- a/arch/x86/include/asm/mach-voyager/entry_arch.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2002
- *
- * Author: James.Bottomley@HansenPartnership.com
- *
- * linux/arch/i386/voyager/entry_arch.h
- *
- * This file builds the VIC and QIC CPI gates
- */
-
-/* initialise the voyager interrupt gates
- *
- * This uses the macros in irq.h to set up assembly jump gates. The
- * calls are then redirected to the same routine with smp_ prefixed */
-BUILD_INTERRUPT(vic_sys_interrupt, VIC_SYS_INT)
-BUILD_INTERRUPT(vic_cmn_interrupt, VIC_CMN_INT)
-BUILD_INTERRUPT(vic_cpi_interrupt, VIC_CPI_LEVEL0);
-
-/* do all the QIC interrupts */
-BUILD_INTERRUPT(qic_timer_interrupt, QIC_TIMER_CPI);
-BUILD_INTERRUPT(qic_invalidate_interrupt, QIC_INVALIDATE_CPI);
-BUILD_INTERRUPT(qic_reschedule_interrupt, QIC_RESCHEDULE_CPI);
-BUILD_INTERRUPT(qic_enable_irq_interrupt, QIC_ENABLE_IRQ_CPI);
-BUILD_INTERRUPT(qic_call_function_interrupt, QIC_CALL_FUNCTION_CPI);
-BUILD_INTERRUPT(qic_call_function_single_interrupt, QIC_CALL_FUNCTION_SINGLE_CPI);
diff --git a/arch/x86/include/asm/mach-voyager/setup_arch.h b/arch/x86/include/asm/mach-voyager/setup_arch.h
deleted file mode 100644
index 71729ca05cd7..000000000000
--- a/arch/x86/include/asm/mach-voyager/setup_arch.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <asm/voyager.h>
-#include <asm/setup.h>
-#define VOYAGER_BIOS_INFO ((struct voyager_bios_info *) \
- (&boot_params.apm_bios_info))
-
-/* Hook to call BIOS initialisation function */
-
-/* for voyager, pass the voyager BIOS/SUS info area to the detection
- * routines */
-
-#define ARCH_SETUP voyager_detect(VOYAGER_BIOS_INFO);
-
diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h
index 07f1af494ca5..105fb90a0635 100644
--- a/arch/x86/include/asm/mmzone_32.h
+++ b/arch/x86/include/asm/mmzone_32.h
@@ -32,8 +32,6 @@ static inline void get_memcfg_numa(void)
get_memcfg_numa_flat();
}
-extern int early_pfn_to_nid(unsigned long pfn);
-
extern void resume_map_numa_kva(pgd_t *pgd);
#else /* !CONFIG_NUMA */
diff --git a/arch/x86/include/asm/mmzone_64.h b/arch/x86/include/asm/mmzone_64.h
index a5b3817d4b9e..a29f48c2a322 100644
--- a/arch/x86/include/asm/mmzone_64.h
+++ b/arch/x86/include/asm/mmzone_64.h
@@ -40,8 +40,6 @@ static inline __attribute__((pure)) int phys_to_nid(unsigned long addr)
#define node_end_pfn(nid) (NODE_DATA(nid)->node_start_pfn + \
NODE_DATA(nid)->node_spanned_pages)
-extern int early_pfn_to_nid(unsigned long pfn);
-
#ifdef CONFIG_NUMA_EMU
#define FAKE_NODE_MIN_SIZE (64 * 1024 * 1024)
#define FAKE_NODE_MIN_HASH_MASK (~(FAKE_NODE_MIN_SIZE - 1UL))
diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h
index 5916c8df09d9..642fc7fc8cdc 100644
--- a/arch/x86/include/asm/mpspec.h
+++ b/arch/x86/include/asm/mpspec.h
@@ -167,6 +167,4 @@ extern int generic_mps_oem_check(struct mpc_table *, char *, char *);
extern int default_acpi_madt_oem_check(char *, char *);
-extern void numaq_mps_oem_check(struct mpc_table *, char *, char *);
-
#endif /* _ASM_X86_MPSPEC_H */
diff --git a/arch/x86/include/asm/page_32_types.h b/arch/x86/include/asm/page_32_types.h
index b5486aaf36ec..f1e4a79a6e41 100644
--- a/arch/x86/include/asm/page_32_types.h
+++ b/arch/x86/include/asm/page_32_types.h
@@ -33,12 +33,10 @@
/* 44=32+12, the limit we can fit into an unsigned long pfn */
#define __PHYSICAL_MASK_SHIFT 44
#define __VIRTUAL_MASK_SHIFT 32
-#define PAGETABLE_LEVELS 3
#else /* !CONFIG_X86_PAE */
#define __PHYSICAL_MASK_SHIFT 32
#define __VIRTUAL_MASK_SHIFT 32
-#define PAGETABLE_LEVELS 2
#endif /* CONFIG_X86_PAE */
#ifndef __ASSEMBLY__
diff --git a/arch/x86/include/asm/page_64_types.h b/arch/x86/include/asm/page_64_types.h
index bc73af3eda9c..d38c91b70248 100644
--- a/arch/x86/include/asm/page_64_types.h
+++ b/arch/x86/include/asm/page_64_types.h
@@ -1,8 +1,6 @@
#ifndef _ASM_X86_PAGE_64_DEFS_H
#define _ASM_X86_PAGE_64_DEFS_H
-#define PAGETABLE_LEVELS 4
-
#define THREAD_ORDER 1
#define THREAD_SIZE (PAGE_SIZE << THREAD_ORDER)
#define CURRENT_MASK (~(THREAD_SIZE - 1))
diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h
index 2c52ff767584..2d625da6603c 100644
--- a/arch/x86/include/asm/page_types.h
+++ b/arch/x86/include/asm/page_types.h
@@ -16,12 +16,6 @@
(ie, 32-bit PAE). */
#define PHYSICAL_PAGE_MASK (((signed long)PAGE_MASK) & __PHYSICAL_MASK)
-/* PTE_PFN_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
-#define PTE_PFN_MASK ((pteval_t)PHYSICAL_PAGE_MASK)
-
-/* PTE_FLAGS_MASK extracts the flags from a (pte|pmd|pud|pgd)val_t */
-#define PTE_FLAGS_MASK (~PTE_PFN_MASK)
-
#define PMD_PAGE_SIZE (_AC(1, UL) << PMD_SHIFT)
#define PMD_PAGE_MASK (~(PMD_PAGE_SIZE-1))
diff --git a/arch/x86/include/asm/pgtable-2level_types.h b/arch/x86/include/asm/pgtable-2level_types.h
index 09ae67efcebd..daacc23e3fb9 100644
--- a/arch/x86/include/asm/pgtable-2level_types.h
+++ b/arch/x86/include/asm/pgtable-2level_types.h
@@ -17,6 +17,7 @@ typedef union {
#endif /* !__ASSEMBLY__ */
#define SHARED_KERNEL_PMD 0
+#define PAGETABLE_LEVELS 2
/*
* traditional i386 two-level paging structure:
@@ -25,6 +26,7 @@ typedef union {
#define PGDIR_SHIFT 22
#define PTRS_PER_PGD 1024
+
/*
* the i386 is two-level, so we don't really have any
* PMD directory physically.
diff --git a/arch/x86/include/asm/pgtable-3level_types.h b/arch/x86/include/asm/pgtable-3level_types.h
index bcc89625ebe5..1bd5876c8649 100644
--- a/arch/x86/include/asm/pgtable-3level_types.h
+++ b/arch/x86/include/asm/pgtable-3level_types.h
@@ -24,6 +24,8 @@ typedef union {
#define SHARED_KERNEL_PMD 1
#endif
+#define PAGETABLE_LEVELS 3
+
/*
* PGDIR_SHIFT determines what a top-level page table entry can map
*/
diff --git a/arch/x86/include/asm/pgtable_64_types.h b/arch/x86/include/asm/pgtable_64_types.h
index 2f59135c6f2a..fbf42b8e0383 100644
--- a/arch/x86/include/asm/pgtable_64_types.h
+++ b/arch/x86/include/asm/pgtable_64_types.h
@@ -18,6 +18,7 @@ typedef struct { pteval_t pte; } pte_t;
#endif /* !__ASSEMBLY__ */
#define SHARED_KERNEL_PMD 0
+#define PAGETABLE_LEVELS 4
/*
* PGDIR_SHIFT determines what a top-level page table entry can map
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 9dafe87be2de..4d258ad76a0f 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -173,6 +173,12 @@
#include <linux/types.h>
+/* PTE_PFN_MASK extracts the PFN from a (pte|pmd|pud|pgd)val_t */
+#define PTE_PFN_MASK ((pteval_t)PHYSICAL_PAGE_MASK)
+
+/* PTE_FLAGS_MASK extracts the flags from a (pte|pmd|pud|pgd)val_t */
+#define PTE_FLAGS_MASK (~PTE_PFN_MASK)
+
typedef struct pgprot { pgprotval_t pgprot; } pgprot_t;
typedef struct { pgdval_t pgd; } pgd_t;
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index dabab1a19ddd..c7a98f738210 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -403,7 +403,6 @@ DECLARE_PER_CPU(unsigned long, stack_canary);
#endif
#endif /* X86_64 */
-extern void print_cpu_info(struct cpuinfo_x86 *);
extern unsigned int xstate_size;
extern void free_thread_xstate(struct task_struct *);
extern struct kmem_cache *task_xstate_cachep;
@@ -862,6 +861,7 @@ static inline void spin_lock_prefetch(const void *x)
* User space process size: 3GB (default).
*/
#define TASK_SIZE PAGE_OFFSET
+#define TASK_SIZE_MAX TASK_SIZE
#define STACK_TOP TASK_SIZE
#define STACK_TOP_MAX STACK_TOP
@@ -921,7 +921,7 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
/*
* User space process size. 47bits minus one guard page.
*/
-#define TASK_SIZE64 ((1UL << 47) - PAGE_SIZE)
+#define TASK_SIZE_MAX ((1UL << 47) - PAGE_SIZE)
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
@@ -930,12 +930,12 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
0xc0000000 : 0xFFFFe000)
#define TASK_SIZE (test_thread_flag(TIF_IA32) ? \
- IA32_PAGE_OFFSET : TASK_SIZE64)
+ IA32_PAGE_OFFSET : TASK_SIZE_MAX)
#define TASK_SIZE_OF(child) ((test_tsk_thread_flag(child, TIF_IA32)) ? \
- IA32_PAGE_OFFSET : TASK_SIZE64)
+ IA32_PAGE_OFFSET : TASK_SIZE_MAX)
#define STACK_TOP TASK_SIZE
-#define STACK_TOP_MAX TASK_SIZE64
+#define STACK_TOP_MAX TASK_SIZE_MAX
#define INIT_THREAD { \
.sp0 = (unsigned long)&init_stack + sizeof(init_stack) \
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index c230189462a2..66801cb72f69 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -13,6 +13,7 @@
struct mpc_cpu;
struct mpc_bus;
struct mpc_oemtable;
+
struct x86_quirks {
int (*arch_pre_time_init)(void);
int (*arch_time_init)(void);
@@ -30,9 +31,17 @@ struct x86_quirks {
void (*smp_read_mpc_oem)(struct mpc_oemtable *oemtable,
unsigned short oemsize);
int (*setup_ioapic_ids)(void);
- int (*update_genapic)(void);
+ int (*update_apic)(void);
};
+extern void x86_quirk_pre_intr_init(void);
+extern void x86_quirk_intr_init(void);
+
+extern void x86_quirk_trap_init(void);
+
+extern void x86_quirk_pre_time_init(void);
+extern void x86_quirk_time_init(void);
+
#endif /* __ASSEMBLY__ */
#ifdef __i386__
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index 258ef730aaa4..7043408f6904 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -82,7 +82,7 @@ asmlinkage long sys_iopl(unsigned int, struct pt_regs *);
/* kernel/signal_64.c */
asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *,
struct pt_regs *);
-asmlinkage long sys_rt_sigreturn(struct pt_regs *);
+long sys_rt_sigreturn(struct pt_regs *);
/* kernel/sys_x86_64.c */
asmlinkage long sys_mmap(unsigned long, unsigned long, unsigned long,
diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h
index 2bb6a835c453..a81195eaa2b3 100644
--- a/arch/x86/include/asm/timer.h
+++ b/arch/x86/include/asm/timer.h
@@ -3,6 +3,7 @@
#include <linux/init.h>
#include <linux/pm.h>
#include <linux/percpu.h>
+#include <linux/interrupt.h>
#define TICK_SIZE (tick_nsec / 1000)
@@ -12,6 +13,7 @@ unsigned long native_calibrate_tsc(void);
#ifdef CONFIG_X86_32
extern int timer_ack;
extern int recalibrate_cpu_khz(void);
+extern irqreturn_t timer_interrupt(int irq, void *dev_id);
#endif /* CONFIG_X86_32 */
extern int no_timer_check;
diff --git a/arch/x86/include/asm/vic.h b/arch/x86/include/asm/vic.h
deleted file mode 100644
index 53100f353612..000000000000
--- a/arch/x86/include/asm/vic.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* Copyright (C) 1999,2001
- *
- * Author: J.E.J.Bottomley@HansenPartnership.com
- *
- * Standard include definitions for the NCR Voyager Interrupt Controller */
-
-/* The eight CPI vectors. To activate a CPI, you write a bit mask
- * corresponding to the processor set to be interrupted into the
- * relevant register. That set of CPUs will then be interrupted with
- * the CPI */
-static const int VIC_CPI_Registers[] =
- {0xFC00, 0xFC01, 0xFC08, 0xFC09,
- 0xFC10, 0xFC11, 0xFC18, 0xFC19 };
-
-#define VIC_PROC_WHO_AM_I 0xfc29
-# define QUAD_IDENTIFIER 0xC0
-# define EIGHT_SLOT_IDENTIFIER 0xE0
-#define QIC_EXTENDED_PROCESSOR_SELECT 0xFC72
-#define VIC_CPI_BASE_REGISTER 0xFC41
-#define VIC_PROCESSOR_ID 0xFC21
-# define VIC_CPU_MASQUERADE_ENABLE 0x8
-
-#define VIC_CLAIM_REGISTER_0 0xFC38
-#define VIC_CLAIM_REGISTER_1 0xFC39
-#define VIC_REDIRECT_REGISTER_0 0xFC60
-#define VIC_REDIRECT_REGISTER_1 0xFC61
-#define VIC_PRIORITY_REGISTER 0xFC20
-
-#define VIC_PRIMARY_MC_BASE 0xFC48
-#define VIC_SECONDARY_MC_BASE 0xFC49
-
-#define QIC_PROCESSOR_ID 0xFC71
-# define QIC_CPUID_ENABLE 0x08
-
-#define QIC_VIC_CPI_BASE_REGISTER 0xFC79
-#define QIC_CPI_BASE_REGISTER 0xFC7A
-
-#define QIC_MASK_REGISTER0 0xFC80
-/* NOTE: these are masked high, enabled low */
-# define QIC_PERF_TIMER 0x01
-# define QIC_LPE 0x02
-# define QIC_SYS_INT 0x04
-# define QIC_CMN_INT 0x08
-/* at the moment, just enable CMN_INT, disable SYS_INT */
-# define QIC_DEFAULT_MASK0 (~(QIC_CMN_INT /* | VIC_SYS_INT */))
-#define QIC_MASK_REGISTER1 0xFC81
-# define QIC_BOOT_CPI_MASK 0xFE
-/* Enable CPI's 1-6 inclusive */
-# define QIC_CPI_ENABLE 0x81
-
-#define QIC_INTERRUPT_CLEAR0 0xFC8A
-#define QIC_INTERRUPT_CLEAR1 0xFC8B
-
-/* this is where we place the CPI vectors */
-#define VIC_DEFAULT_CPI_BASE 0xC0
-/* this is where we place the QIC CPI vectors */
-#define QIC_DEFAULT_CPI_BASE 0xD0
-
-#define VIC_BOOT_INTERRUPT_MASK 0xfe
-
-extern void smp_vic_timer_interrupt(void);
diff --git a/arch/x86/include/asm/voyager.h b/arch/x86/include/asm/voyager.h
deleted file mode 100644
index c1635d43616f..000000000000
--- a/arch/x86/include/asm/voyager.h
+++ /dev/null
@@ -1,571 +0,0 @@
-/* Copyright (C) 1999,2001
- *
- * Author: J.E.J.Bottomley@HansenPartnership.com
- *
- * Standard include definitions for the NCR Voyager system */
-
-#undef VOYAGER_DEBUG
-#undef VOYAGER_CAT_DEBUG
-
-#ifdef VOYAGER_DEBUG
-#define VDEBUG(x) printk x
-#else
-#define VDEBUG(x)
-#endif
-
-/* There are three levels of voyager machine: 3,4 and 5. The rule is
- * if it's less than 3435 it's a Level 3 except for a 3360 which is
- * a level 4. A 3435 or above is a Level 5 */
-#define VOYAGER_LEVEL5_AND_ABOVE 0x3435
-#define VOYAGER_LEVEL4 0x3360
-
-/* The L4 DINO ASIC */
-#define VOYAGER_DINO 0x43
-
-/* voyager ports in standard I/O space */
-#define VOYAGER_MC_SETUP 0x96
-
-
-#define VOYAGER_CAT_CONFIG_PORT 0x97
-# define VOYAGER_CAT_DESELECT 0xff
-#define VOYAGER_SSPB_RELOCATION_PORT 0x98
-
-/* Valid CAT controller commands */
-/* start instruction register cycle */
-#define VOYAGER_CAT_IRCYC 0x01
-/* start data register cycle */
-#define VOYAGER_CAT_DRCYC 0x02
-/* move to execute state */
-#define VOYAGER_CAT_RUN 0x0F
-/* end operation */
-#define VOYAGER_CAT_END 0x80
-/* hold in idle state */
-#define VOYAGER_CAT_HOLD 0x90
-/* single step an "intest" vector */
-#define VOYAGER_CAT_STEP 0xE0
-/* return cat controller to CLEMSON mode */
-#define VOYAGER_CAT_CLEMSON 0xFF
-
-/* the default cat command header */
-#define VOYAGER_CAT_HEADER 0x7F
-
-/* the range of possible CAT module ids in the system */
-#define VOYAGER_MIN_MODULE 0x10
-#define VOYAGER_MAX_MODULE 0x1f
-
-/* The voyager registers per asic */
-#define VOYAGER_ASIC_ID_REG 0x00
-#define VOYAGER_ASIC_TYPE_REG 0x01
-/* the sub address registers can be made auto incrementing on reads */
-#define VOYAGER_AUTO_INC_REG 0x02
-# define VOYAGER_AUTO_INC 0x04
-# define VOYAGER_NO_AUTO_INC 0xfb
-#define VOYAGER_SUBADDRDATA 0x03
-#define VOYAGER_SCANPATH 0x05
-# define VOYAGER_CONNECT_ASIC 0x01
-# define VOYAGER_DISCONNECT_ASIC 0xfe
-#define VOYAGER_SUBADDRLO 0x06
-#define VOYAGER_SUBADDRHI 0x07
-#define VOYAGER_SUBMODSELECT 0x08
-#define VOYAGER_SUBMODPRESENT 0x09
-
-#define VOYAGER_SUBADDR_LO 0xff
-#define VOYAGER_SUBADDR_HI 0xffff
-
-/* the maximum size of a scan path -- used to form instructions */
-#define VOYAGER_MAX_SCAN_PATH 0x100
-/* the biggest possible register size (in bytes) */
-#define VOYAGER_MAX_REG_SIZE 4
-
-/* Total number of possible modules (including submodules) */
-#define VOYAGER_MAX_MODULES 16
-/* Largest number of asics per module */
-#define VOYAGER_MAX_ASICS_PER_MODULE 7
-
-/* the CAT asic of each module is always the first one */
-#define VOYAGER_CAT_ID 0
-#define VOYAGER_PSI 0x1a
-
-/* voyager instruction operations and registers */
-#define VOYAGER_READ_CONFIG 0x1
-#define VOYAGER_WRITE_CONFIG 0x2
-#define VOYAGER_BYPASS 0xff
-
-typedef struct voyager_asic {
- __u8 asic_addr; /* ASIC address; Level 4 */
- __u8 asic_type; /* ASIC type */
- __u8 asic_id; /* ASIC id */
- __u8 jtag_id[4]; /* JTAG id */
- __u8 asic_location; /* Location within scan path; start w/ 0 */
- __u8 bit_location; /* Location within bit stream; start w/ 0 */
- __u8 ireg_length; /* Instruction register length */
- __u16 subaddr; /* Amount of sub address space */
- struct voyager_asic *next; /* Next asic in linked list */
-} voyager_asic_t;
-
-typedef struct voyager_module {
- __u8 module_addr; /* Module address */
- __u8 scan_path_connected; /* Scan path connected */
- __u16 ee_size; /* Size of the EEPROM */
- __u16 num_asics; /* Number of Asics */
- __u16 inst_bits; /* Instruction bits in the scan path */
- __u16 largest_reg; /* Largest register in the scan path */
- __u16 smallest_reg; /* Smallest register in the scan path */
- voyager_asic_t *asic; /* First ASIC in scan path (CAT_I) */
- struct voyager_module *submodule; /* Submodule pointer */
- struct voyager_module *next; /* Next module in linked list */
-} voyager_module_t;
-
-typedef struct voyager_eeprom_hdr {
- __u8 module_id[4];
- __u8 version_id;
- __u8 config_id;
- __u16 boundry_id; /* boundary scan id */
- __u16 ee_size; /* size of EEPROM */
- __u8 assembly[11]; /* assembly # */
- __u8 assembly_rev; /* assembly rev */
- __u8 tracer[4]; /* tracer number */
- __u16 assembly_cksum; /* asm checksum */
- __u16 power_consump; /* pwr requirements */
- __u16 num_asics; /* number of asics */
- __u16 bist_time; /* min. bist time */
- __u16 err_log_offset; /* error log offset */
- __u16 scan_path_offset;/* scan path offset */
- __u16 cct_offset;
- __u16 log_length; /* length of err log */
- __u16 xsum_end; /* offset to end of
- checksum */
- __u8 reserved[4];
- __u8 sflag; /* starting sentinal */
- __u8 part_number[13]; /* prom part number */
- __u8 version[10]; /* version number */
- __u8 signature[8];
- __u16 eeprom_chksum;
- __u32 data_stamp_offset;
- __u8 eflag ; /* ending sentinal */
-} __attribute__((packed)) voyager_eprom_hdr_t;
-
-
-
-#define VOYAGER_EPROM_SIZE_OFFSET \
- ((__u16)(&(((voyager_eprom_hdr_t *)0)->ee_size)))
-#define VOYAGER_XSUM_END_OFFSET 0x2a
-
-/* the following three definitions are for internal table layouts
- * in the module EPROMs. We really only care about the IDs and
- * offsets */
-typedef struct voyager_sp_table {
- __u8 asic_id;
- __u8 bypass_flag;
- __u16 asic_data_offset;
- __u16 config_data_offset;
-} __attribute__((packed)) voyager_sp_table_t;
-
-typedef struct voyager_jtag_table {
- __u8 icode[4];
- __u8 runbist[4];
- __u8 intest[4];
- __u8 samp_preld[4];
- __u8 ireg_len;
-} __attribute__((packed)) voyager_jtt_t;
-
-typedef struct voyager_asic_data_table {
- __u8 jtag_id[4];
- __u16 length_bsr;
- __u16 length_bist_reg;
- __u32 bist_clk;
- __u16 subaddr_bits;
- __u16 seed_bits;
- __u16 sig_bits;
- __u16 jtag_offset;
-} __attribute__((packed)) voyager_at_t;
-
-/* Voyager Interrupt Controller (VIC) registers */
-
-/* Base to add to Cross Processor Interrupts (CPIs) when triggering
- * the CPU IRQ line */
-/* register defines for the WCBICs (one per processor) */
-#define VOYAGER_WCBIC0 0x41 /* bus A node P1 processor 0 */
-#define VOYAGER_WCBIC1 0x49 /* bus A node P1 processor 1 */
-#define VOYAGER_WCBIC2 0x51 /* bus A node P2 processor 0 */
-#define VOYAGER_WCBIC3 0x59 /* bus A node P2 processor 1 */
-#define VOYAGER_WCBIC4 0x61 /* bus B node P1 processor 0 */
-#define VOYAGER_WCBIC5 0x69 /* bus B node P1 processor 1 */
-#define VOYAGER_WCBIC6 0x71 /* bus B node P2 processor 0 */
-#define VOYAGER_WCBIC7 0x79 /* bus B node P2 processor 1 */
-
-
-/* top of memory registers */
-#define VOYAGER_WCBIC_TOM_L 0x4
-#define VOYAGER_WCBIC_TOM_H 0x5
-
-/* register defines for Voyager Memory Contol (VMC)
- * these are present on L4 machines only */
-#define VOYAGER_VMC1 0x81
-#define VOYAGER_VMC2 0x91
-#define VOYAGER_VMC3 0xa1
-#define VOYAGER_VMC4 0xb1
-
-/* VMC Ports */
-#define VOYAGER_VMC_MEMORY_SETUP 0x9
-# define VMC_Interleaving 0x01
-# define VMC_4Way 0x02
-# define VMC_EvenCacheLines 0x04
-# define VMC_HighLine 0x08
-# define VMC_Start0_Enable 0x20
-# define VMC_Start1_Enable 0x40
-# define VMC_Vremap 0x80
-#define VOYAGER_VMC_BANK_DENSITY 0xa
-# define VMC_BANK_EMPTY 0
-# define VMC_BANK_4MB 1
-# define VMC_BANK_16MB 2
-# define VMC_BANK_64MB 3
-# define VMC_BANK0_MASK 0x03
-# define VMC_BANK1_MASK 0x0C
-# define VMC_BANK2_MASK 0x30
-# define VMC_BANK3_MASK 0xC0
-
-/* Magellan Memory Controller (MMC) defines - present on L5 */
-#define VOYAGER_MMC_ASIC_ID 1
-/* the two memory modules corresponding to memory cards in the system */
-#define VOYAGER_MMC_MEMORY0_MODULE 0x14
-#define VOYAGER_MMC_MEMORY1_MODULE 0x15
-/* the Magellan Memory Address (MMA) defines */
-#define VOYAGER_MMA_ASIC_ID 2
-
-/* Submodule number for the Quad Baseboard */
-#define VOYAGER_QUAD_BASEBOARD 1
-
-/* ASIC defines for the Quad Baseboard */
-#define VOYAGER_QUAD_QDATA0 1
-#define VOYAGER_QUAD_QDATA1 2
-#define VOYAGER_QUAD_QABC 3
-
-/* Useful areas in extended CMOS */
-#define VOYAGER_PROCESSOR_PRESENT_MASK 0x88a
-#define VOYAGER_MEMORY_CLICKMAP 0xa23
-#define VOYAGER_DUMP_LOCATION 0xb1a
-
-/* SUS In Control bit - used to tell SUS that we don't need to be
- * babysat anymore */
-#define VOYAGER_SUS_IN_CONTROL_PORT 0x3ff
-# define VOYAGER_IN_CONTROL_FLAG 0x80
-
-/* Voyager PSI defines */
-#define VOYAGER_PSI_STATUS_REG 0x08
-# define PSI_DC_FAIL 0x01
-# define PSI_MON 0x02
-# define PSI_FAULT 0x04
-# define PSI_ALARM 0x08
-# define PSI_CURRENT 0x10
-# define PSI_DVM 0x20
-# define PSI_PSCFAULT 0x40
-# define PSI_STAT_CHG 0x80
-
-#define VOYAGER_PSI_SUPPLY_REG 0x8000
- /* read */
-# define PSI_FAIL_DC 0x01
-# define PSI_FAIL_AC 0x02
-# define PSI_MON_INT 0x04
-# define PSI_SWITCH_OFF 0x08
-# define PSI_HX_OFF 0x10
-# define PSI_SECURITY 0x20
-# define PSI_CMOS_BATT_LOW 0x40
-# define PSI_CMOS_BATT_FAIL 0x80
- /* write */
-# define PSI_CLR_SWITCH_OFF 0x13
-# define PSI_CLR_HX_OFF 0x14
-# define PSI_CLR_CMOS_BATT_FAIL 0x17
-
-#define VOYAGER_PSI_MASK 0x8001
-# define PSI_MASK_MASK 0x10
-
-#define VOYAGER_PSI_AC_FAIL_REG 0x8004
-#define AC_FAIL_STAT_CHANGE 0x80
-
-#define VOYAGER_PSI_GENERAL_REG 0x8007
- /* read */
-# define PSI_SWITCH_ON 0x01
-# define PSI_SWITCH_ENABLED 0x02
-# define PSI_ALARM_ENABLED 0x08
-# define PSI_SECURE_ENABLED 0x10
-# define PSI_COLD_RESET 0x20
-# define PSI_COLD_START 0x80
- /* write */
-# define PSI_POWER_DOWN 0x10
-# define PSI_SWITCH_DISABLE 0x01
-# define PSI_SWITCH_ENABLE 0x11
-# define PSI_CLEAR 0x12
-# define PSI_ALARM_DISABLE 0x03
-# define PSI_ALARM_ENABLE 0x13
-# define PSI_CLEAR_COLD_RESET 0x05
-# define PSI_SET_COLD_RESET 0x15
-# define PSI_CLEAR_COLD_START 0x07
-# define PSI_SET_COLD_START 0x17
-
-
-
-struct voyager_bios_info {
- __u8 len;
- __u8 major;
- __u8 minor;
- __u8 debug;
- __u8 num_classes;
- __u8 class_1;
- __u8 class_2;
-};
-
-/* The following structures and definitions are for the Kernel/SUS
- * interface these are needed to find out how SUS initialised any Quad
- * boards in the system */
-
-#define NUMBER_OF_MC_BUSSES 2
-#define SLOTS_PER_MC_BUS 8
-#define MAX_CPUS 16 /* 16 way CPU system */
-#define MAX_PROCESSOR_BOARDS 4 /* 4 processor slot system */
-#define MAX_CACHE_LEVELS 4 /* # of cache levels supported */
-#define MAX_SHARED_CPUS 4 /* # of CPUs that can share a LARC */
-#define NUMBER_OF_POS_REGS 8
-
-typedef struct {
- __u8 MC_Slot;
- __u8 POS_Values[NUMBER_OF_POS_REGS];
-} __attribute__((packed)) MC_SlotInformation_t;
-
-struct QuadDescription {
- __u8 Type; /* for type 0 (DYADIC or MONADIC) all fields
- * will be zero except for slot */
- __u8 StructureVersion;
- __u32 CPI_BaseAddress;
- __u32 LARC_BankSize;
- __u32 LocalMemoryStateBits;
- __u8 Slot; /* Processor slots 1 - 4 */
-} __attribute__((packed));
-
-struct ProcBoardInfo {
- __u8 Type;
- __u8 StructureVersion;
- __u8 NumberOfBoards;
- struct QuadDescription QuadData[MAX_PROCESSOR_BOARDS];
-} __attribute__((packed));
-
-struct CacheDescription {
- __u8 Level;
- __u32 TotalSize;
- __u16 LineSize;
- __u8 Associativity;
- __u8 CacheType;
- __u8 WriteType;
- __u8 Number_CPUs_SharedBy;
- __u8 Shared_CPUs_Hardware_IDs[MAX_SHARED_CPUS];
-
-} __attribute__((packed));
-
-struct CPU_Description {
- __u8 CPU_HardwareId;
- char *FRU_String;
- __u8 NumberOfCacheLevels;
- struct CacheDescription CacheLevelData[MAX_CACHE_LEVELS];
-} __attribute__((packed));
-
-struct CPU_Info {
- __u8 Type;
- __u8 StructureVersion;
- __u8 NumberOf_CPUs;
- struct CPU_Description CPU_Data[MAX_CPUS];
-} __attribute__((packed));
-
-
-/*
- * This structure will be used by SUS and the OS.
- * The assumption about this structure is that no blank space is
- * packed in it by our friend the compiler.
- */
-typedef struct {
- __u8 Mailbox_SUS; /* Written to by SUS to give
- commands/response to the OS */
- __u8 Mailbox_OS; /* Written to by the OS to give
- commands/response to SUS */
- __u8 SUS_MailboxVersion; /* Tells the OS which iteration of the
- interface SUS supports */
- __u8 OS_MailboxVersion; /* Tells SUS which iteration of the
- interface the OS supports */
- __u32 OS_Flags; /* Flags set by the OS as info for
- SUS */
- __u32 SUS_Flags; /* Flags set by SUS as info
- for the OS */
- __u32 WatchDogPeriod; /* Watchdog period (in seconds) which
- the DP uses to see if the OS
- is dead */
- __u32 WatchDogCount; /* Updated by the OS on every tic. */
- __u32 MemoryFor_SUS_ErrorLog; /* Flat 32 bit address which tells SUS
- where to stuff the SUS error log
- on a dump */
- MC_SlotInformation_t MC_SlotInfo[NUMBER_OF_MC_BUSSES*SLOTS_PER_MC_BUS];
- /* Storage for MCA POS data */
- /* All new SECOND_PASS_INTERFACE fields added from this point */
- struct ProcBoardInfo *BoardData;
- struct CPU_Info *CPU_Data;
- /* All new fields must be added from this point */
-} Voyager_KernelSUS_Mbox_t;
-
-/* structure for finding the right memory address to send a QIC CPI to */
-struct voyager_qic_cpi {
- /* Each cache line (32 bytes) can trigger a cpi. The cpi
- * read/write may occur anywhere in the cache line---pick the
- * middle to be safe */
- struct {
- __u32 pad1[3];
- __u32 cpi;
- __u32 pad2[4];
- } qic_cpi[8];
-};
-
-struct voyager_status {
- __u32 power_fail:1;
- __u32 switch_off:1;
- __u32 request_from_kernel:1;
-};
-
-struct voyager_psi_regs {
- __u8 cat_id;
- __u8 cat_dev;
- __u8 cat_control;
- __u8 subaddr;
- __u8 dummy4;
- __u8 checkbit;
- __u8 subaddr_low;
- __u8 subaddr_high;
- __u8 intstatus;
- __u8 stat1;
- __u8 stat3;
- __u8 fault;
- __u8 tms;
- __u8 gen;
- __u8 sysconf;
- __u8 dummy15;
-};
-
-struct voyager_psi_subregs {
- __u8 supply;
- __u8 mask;
- __u8 present;
- __u8 DCfail;
- __u8 ACfail;
- __u8 fail;
- __u8 UPSfail;
- __u8 genstatus;
-};
-
-struct voyager_psi {
- struct voyager_psi_regs regs;
- struct voyager_psi_subregs subregs;
-};
-
-struct voyager_SUS {
-#define VOYAGER_DUMP_BUTTON_NMI 0x1
-#define VOYAGER_SUS_VALID 0x2
-#define VOYAGER_SYSINT_COMPLETE 0x3
- __u8 SUS_mbox;
-#define VOYAGER_NO_COMMAND 0x0
-#define VOYAGER_IGNORE_DUMP 0x1
-#define VOYAGER_DO_DUMP 0x2
-#define VOYAGER_SYSINT_HANDSHAKE 0x3
-#define VOYAGER_DO_MEM_DUMP 0x4
-#define VOYAGER_SYSINT_WAS_RECOVERED 0x5
- __u8 kernel_mbox;
-#define VOYAGER_MAILBOX_VERSION 0x10
- __u8 SUS_version;
- __u8 kernel_version;
-#define VOYAGER_OS_HAS_SYSINT 0x1
-#define VOYAGER_OS_IN_PROGRESS 0x2
-#define VOYAGER_UPDATING_WDPERIOD 0x4
- __u32 kernel_flags;
-#define VOYAGER_SUS_BOOTING 0x1
-#define VOYAGER_SUS_IN_PROGRESS 0x2
- __u32 SUS_flags;
- __u32 watchdog_period;
- __u32 watchdog_count;
- __u32 SUS_errorlog;
- /* lots of system configuration stuff under here */
-};
-
-/* Variables exported by voyager_smp */
-extern __u32 voyager_extended_vic_processors;
-extern __u32 voyager_allowed_boot_processors;
-extern __u32 voyager_quad_processors;
-extern struct voyager_qic_cpi *voyager_quad_cpi_addr[NR_CPUS];
-extern struct voyager_SUS *voyager_SUS;
-
-/* variables exported always */
-extern struct task_struct *voyager_thread;
-extern int voyager_level;
-extern struct voyager_status voyager_status;
-
-/* functions exported by the voyager and voyager_smp modules */
-extern int voyager_cat_readb(__u8 module, __u8 asic, int reg);
-extern void voyager_cat_init(void);
-extern void voyager_detect(struct voyager_bios_info *);
-extern void voyager_trap_init(void);
-extern void voyager_setup_irqs(void);
-extern int voyager_memory_detect(int region, __u32 *addr, __u32 *length);
-extern void voyager_smp_intr_init(void);
-extern __u8 voyager_extended_cmos_read(__u16 cmos_address);
-extern void voyager_smp_dump(void);
-extern void voyager_timer_interrupt(void);
-extern void smp_local_timer_interrupt(void);
-extern void voyager_power_off(void);
-extern void smp_voyager_power_off(void *dummy);
-extern void voyager_restart(void);
-extern void voyager_cat_power_off(void);
-extern void voyager_cat_do_common_interrupt(void);
-extern void voyager_handle_nmi(void);
-extern void voyager_smp_intr_init(void);
-/* Commands for the following are */
-#define VOYAGER_PSI_READ 0
-#define VOYAGER_PSI_WRITE 1
-#define VOYAGER_PSI_SUBREAD 2
-#define VOYAGER_PSI_SUBWRITE 3
-extern void voyager_cat_psi(__u8, __u16, __u8 *);
-
-/* These define the CPIs we use in linux */
-#define VIC_CPI_LEVEL0 0
-#define VIC_CPI_LEVEL1 1
-/* now the fake CPIs */
-#define VIC_TIMER_CPI 2
-#define VIC_INVALIDATE_CPI 3
-#define VIC_RESCHEDULE_CPI 4
-#define VIC_ENABLE_IRQ_CPI 5
-#define VIC_CALL_FUNCTION_CPI 6
-#define VIC_CALL_FUNCTION_SINGLE_CPI 7
-
-/* Now the QIC CPIs: Since we don't need the two initial levels,
- * these are 2 less than the VIC CPIs */
-#define QIC_CPI_OFFSET 1
-#define QIC_TIMER_CPI (VIC_TIMER_CPI - QIC_CPI_OFFSET)
-#define QIC_INVALIDATE_CPI (VIC_INVALIDATE_CPI - QIC_CPI_OFFSET)
-#define QIC_RESCHEDULE_CPI (VIC_RESCHEDULE_CPI - QIC_CPI_OFFSET)
-#define QIC_ENABLE_IRQ_CPI (VIC_ENABLE_IRQ_CPI - QIC_CPI_OFFSET)
-#define QIC_CALL_FUNCTION_CPI (VIC_CALL_FUNCTION_CPI - QIC_CPI_OFFSET)
-#define QIC_CALL_FUNCTION_SINGLE_CPI (VIC_CALL_FUNCTION_SINGLE_CPI - QIC_CPI_OFFSET)
-
-#define VIC_START_FAKE_CPI VIC_TIMER_CPI
-#define VIC_END_FAKE_CPI VIC_CALL_FUNCTION_SINGLE_CPI
-
-/* this is the SYS_INT CPI. */
-#define VIC_SYS_INT 8
-#define VIC_CMN_INT 15
-
-/* This is the boot CPI for alternate processors. It gets overwritten
- * by the above once the system has activated all available processors */
-#define VIC_CPU_BOOT_CPI VIC_CPI_LEVEL0
-#define VIC_CPU_BOOT_ERRATA_CPI (VIC_CPI_LEVEL0 + 8)
-
-extern asmlinkage void vic_cpi_interrupt(void);
-extern asmlinkage void vic_sys_interrupt(void);
-extern asmlinkage void vic_cmn_interrupt(void);
-extern asmlinkage void qic_timer_interrupt(void);
-extern asmlinkage void qic_invalidate_interrupt(void);
-extern asmlinkage void qic_reschedule_interrupt(void);
-extern asmlinkage void qic_enable_irq_interrupt(void);
-extern asmlinkage void qic_call_function_interrupt(void);
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 24f357e7557a..de5657c039e9 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -30,7 +30,7 @@ obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
obj-y += time_$(BITS).o ioport.o ldt.o dumpstack.o
obj-y += setup.o i8259.o irqinit_$(BITS).o
obj-$(CONFIG_X86_VISWS) += visws_quirks.o
-obj-$(CONFIG_X86_32) += probe_32.o probe_roms_32.o
+obj-$(CONFIG_X86_32) += probe_roms_32.o
obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o
obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
obj-$(CONFIG_X86_64) += syscall_64.o vsyscall_64.o
@@ -58,23 +58,18 @@ obj-$(CONFIG_PCI) += early-quirks.o
apm-y := apm_32.o
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_SMP) += smpboot.o tsc_sync.o ipi.o
+obj-$(CONFIG_SMP) += smpboot.o tsc_sync.o
obj-$(CONFIG_SMP) += setup_percpu.o
obj-$(CONFIG_X86_64_SMP) += tsc_sync.o
obj-$(CONFIG_X86_TRAMPOLINE) += trampoline_$(BITS).o
obj-$(CONFIG_X86_MPPARSE) += mpparse.o
-obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o ipi.o
-obj-$(CONFIG_X86_IO_APIC) += io_apic.o
+obj-y += apic/
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o
obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o
-obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o
-obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
-obj-$(CONFIG_X86_ES7000) += es7000_32.o
-obj-$(CONFIG_X86_SUMMIT) += summit_32.o
obj-y += vsmp_64.o
obj-$(CONFIG_KPROBES) += kprobes.o
obj-$(CONFIG_MODULES) += module_$(BITS).o
@@ -116,17 +111,13 @@ obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o # NB rename without _64
###
# 64 bit specific files
ifeq ($(CONFIG_X86_64),y)
- obj-y += genapic_64.o genapic_flat_64.o
- obj-y += genx2apic_cluster.o
- obj-y += genx2apic_phys.o
- obj-$(CONFIG_X86_UV) += genx2apic_uv_x.o tlb_uv.o
- obj-$(CONFIG_X86_UV) += bios_uv.o uv_irq.o uv_sysfs.o
- obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
- obj-$(CONFIG_AUDIT) += audit_64.o
-
- obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o
- obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o
- obj-$(CONFIG_AMD_IOMMU) += amd_iommu_init.o amd_iommu.o
-
- obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o
+ obj-$(CONFIG_X86_UV) += tlb_uv.o bios_uv.o uv_irq.o uv_sysfs.o
+ obj-$(CONFIG_X86_PM_TIMER) += pmtimer_64.o
+ obj-$(CONFIG_AUDIT) += audit_64.o
+
+ obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o
+ obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o
+ obj-$(CONFIG_AMD_IOMMU) += amd_iommu_init.o amd_iommu.o
+
+ obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o
endif
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 956c1dee6fbe..a18eb7ce2236 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -37,7 +37,6 @@
#include <asm/pgtable.h>
#include <asm/io_apic.h>
#include <asm/apic.h>
-#include <asm/genapic.h>
#include <asm/io.h>
#include <asm/mpspec.h>
#include <asm/smp.h>
diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S
index 3355973b12ac..580b4e296010 100644
--- a/arch/x86/kernel/acpi/realmode/wakeup.S
+++ b/arch/x86/kernel/acpi/realmode/wakeup.S
@@ -3,8 +3,8 @@
*/
#include <asm/segment.h>
#include <asm/msr-index.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
+#include <asm/page_types.h>
+#include <asm/pgtable_types.h>
#include <asm/processor-flags.h>
.code16
diff --git a/arch/x86/kernel/acpi/wakeup_32.S b/arch/x86/kernel/acpi/wakeup_32.S
index a12e6a9fb659..8ded418b0593 100644
--- a/arch/x86/kernel/acpi/wakeup_32.S
+++ b/arch/x86/kernel/acpi/wakeup_32.S
@@ -1,7 +1,7 @@
.section .text.page_aligned
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
# Copyright 2003, 2008 Pavel Machek <pavel@suse.cz>, distribute under GPLv2
diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S
index bcc293423a70..8ea5164cbd04 100644
--- a/arch/x86/kernel/acpi/wakeup_64.S
+++ b/arch/x86/kernel/acpi/wakeup_64.S
@@ -1,8 +1,8 @@
.text
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <asm/pgtable_types.h>
+#include <asm/page_types.h>
#include <asm/msr.h>
#include <asm/asm-offsets.h>
@@ -13,7 +13,6 @@
* Hooray, we are in Long 64-bit mode (but still running in low memory)
*/
ENTRY(wakeup_long64)
-wakeup_long64:
movq saved_magic, %rax
movq $0x123456789abcdef0, %rdx
cmpq %rdx, %rax
@@ -34,16 +33,12 @@ wakeup_long64:
movq saved_rip, %rax
jmp *%rax
+ENDPROC(wakeup_long64)
bogus_64_magic:
jmp bogus_64_magic
- .align 2
- .p2align 4,,15
-.globl do_suspend_lowlevel
- .type do_suspend_lowlevel,@function
-do_suspend_lowlevel:
-.LFB5:
+ENTRY(do_suspend_lowlevel)
subq $8, %rsp
xorl %eax, %eax
call save_processor_state
@@ -67,7 +62,7 @@ do_suspend_lowlevel:
pushfq
popq pt_regs_flags(%rax)
- movq $.L97, saved_rip(%rip)
+ movq $resume_point, saved_rip(%rip)
movq %rsp, saved_rsp
movq %rbp, saved_rbp
@@ -78,14 +73,12 @@ do_suspend_lowlevel:
addq $8, %rsp
movl $3, %edi
xorl %eax, %eax
- jmp acpi_enter_sleep_state
-.L97:
- .p2align 4,,7
-.L99:
- .align 4
- movl $24, %eax
- movw %ax, %ds
+ call acpi_enter_sleep_state
+ /* in case something went wrong, restore the machine status and go on */
+ jmp resume_point
+ .align 4
+resume_point:
/* We don't restore %rax, it must be 0 anyway */
movq $saved_context, %rax
movq saved_context_cr4(%rax), %rbx
@@ -117,12 +110,9 @@ do_suspend_lowlevel:
xorl %eax, %eax
addq $8, %rsp
jmp restore_processor_state
-.LFE5:
-.Lfe5:
- .size do_suspend_lowlevel, .Lfe5-do_suspend_lowlevel
-
+ENDPROC(do_suspend_lowlevel)
+
.data
-ALIGN
ENTRY(saved_rbp) .quad 0
ENTRY(saved_rsi) .quad 0
ENTRY(saved_rdi) .quad 0
diff --git a/arch/x86/kernel/apic/Makefile b/arch/x86/kernel/apic/Makefile
new file mode 100644
index 000000000000..da7b7b9f8bd8
--- /dev/null
+++ b/arch/x86/kernel/apic/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for local APIC drivers and for the IO-APIC code
+#
+
+obj-$(CONFIG_X86_LOCAL_APIC) += apic.o probe_$(BITS).o ipi.o nmi.o
+obj-$(CONFIG_X86_IO_APIC) += io_apic.o
+obj-$(CONFIG_SMP) += ipi.o
+
+ifeq ($(CONFIG_X86_64),y)
+obj-y += apic_flat_64.o
+obj-$(CONFIG_X86_X2APIC) += x2apic_cluster.o
+obj-$(CONFIG_X86_X2APIC) += x2apic_phys.o
+obj-$(CONFIG_X86_UV) += x2apic_uv_x.o
+endif
+
+obj-$(CONFIG_X86_BIGSMP) += bigsmp_32.o
+obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
+obj-$(CONFIG_X86_ES7000) += es7000_32.o
+obj-$(CONFIG_X86_SUMMIT) += summit_32.o
diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic/apic.c
index a894eea9d51a..f9cecdfd05c5 100644
--- a/arch/x86/kernel/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -34,9 +34,7 @@
#include <linux/smp.h>
#include <linux/mm.h>
-#include <asm/arch_hooks.h>
#include <asm/pgalloc.h>
-#include <asm/genapic.h>
#include <asm/atomic.h>
#include <asm/mpspec.h>
#include <asm/i8253.h>
@@ -112,11 +110,7 @@ static __init int setup_apicpmtimer(char *s)
__setup("apicpmtimer", setup_apicpmtimer);
#endif
-#ifdef CONFIG_X86_64
-#define HAVE_X2APIC
-#endif
-
-#ifdef HAVE_X2APIC
+#ifdef CONFIG_X86_X2APIC
int x2apic;
/* x2apic enabled before OS handover */
static int x2apic_preenabled;
@@ -214,18 +208,13 @@ static int modern_apic(void)
return lapic_get_version() >= 0x14;
}
-/*
- * Paravirt kernels also might be using these below ops. So we still
- * use generic apic_read()/apic_write(), which might be pointing to different
- * ops in PARAVIRT case.
- */
-void xapic_wait_icr_idle(void)
+void native_apic_wait_icr_idle(void)
{
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
cpu_relax();
}
-u32 safe_xapic_wait_icr_idle(void)
+u32 native_safe_apic_wait_icr_idle(void)
{
u32 send_status;
int timeout;
@@ -241,13 +230,13 @@ u32 safe_xapic_wait_icr_idle(void)
return send_status;
}
-void xapic_icr_write(u32 low, u32 id)
+void native_apic_icr_write(u32 low, u32 id)
{
apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(id));
apic_write(APIC_ICR, low);
}
-static u64 xapic_icr_read(void)
+u64 native_apic_icr_read(void)
{
u32 icr1, icr2;
@@ -257,54 +246,6 @@ static u64 xapic_icr_read(void)
return icr1 | ((u64)icr2 << 32);
}
-static struct apic_ops xapic_ops = {
- .read = native_apic_mem_read,
- .write = native_apic_mem_write,
- .icr_read = xapic_icr_read,
- .icr_write = xapic_icr_write,
- .wait_icr_idle = xapic_wait_icr_idle,
- .safe_wait_icr_idle = safe_xapic_wait_icr_idle,
-};
-
-struct apic_ops __read_mostly *apic_ops = &xapic_ops;
-EXPORT_SYMBOL_GPL(apic_ops);
-
-#ifdef HAVE_X2APIC
-static void x2apic_wait_icr_idle(void)
-{
- /* no need to wait for icr idle in x2apic */
- return;
-}
-
-static u32 safe_x2apic_wait_icr_idle(void)
-{
- /* no need to wait for icr idle in x2apic */
- return 0;
-}
-
-void x2apic_icr_write(u32 low, u32 id)
-{
- wrmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), ((__u64) id) << 32 | low);
-}
-
-static u64 x2apic_icr_read(void)
-{
- unsigned long val;
-
- rdmsrl(APIC_BASE_MSR + (APIC_ICR >> 4), val);
- return val;
-}
-
-static struct apic_ops x2apic_ops = {
- .read = native_apic_msr_read,
- .write = native_apic_msr_write,
- .icr_read = x2apic_icr_read,
- .icr_write = x2apic_icr_write,
- .wait_icr_idle = x2apic_wait_icr_idle,
- .safe_wait_icr_idle = safe_x2apic_wait_icr_idle,
-};
-#endif
-
/**
* enable_NMI_through_LVT0 - enable NMI through local vector table 0
*/
@@ -895,7 +836,7 @@ void clear_local_APIC(void)
}
/* lets not touch this if we didn't frob it */
-#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(X86_MCE_INTEL)
+#if defined(CONFIG_X86_MCE_P4THERMAL) || defined(CONFIG_X86_MCE_INTEL)
if (maxlvt >= 5) {
v = apic_read(APIC_LVTTHMR);
apic_write(APIC_LVTTHMR, v | APIC_LVT_MASKED);
@@ -1320,17 +1261,12 @@ void __cpuinit end_local_APIC_setup(void)
apic_pm_activate();
}
-#ifdef HAVE_X2APIC
+#ifdef CONFIG_X86_X2APIC
void check_x2apic(void)
{
- int msr, msr2;
-
- rdmsr(MSR_IA32_APICBASE, msr, msr2);
-
- if (msr & X2APIC_ENABLE) {
+ if (x2apic_enabled()) {
pr_info("x2apic enabled by BIOS, switching to x2apic ops\n");
x2apic_preenabled = x2apic = 1;
- apic_ops = &x2apic_ops;
}
}
@@ -1338,6 +1274,9 @@ void enable_x2apic(void)
{
int msr, msr2;
+ if (!x2apic)
+ return;
+
rdmsr(MSR_IA32_APICBASE, msr, msr2);
if (!(msr & X2APIC_ENABLE)) {
pr_info("Enabling x2apic\n");
@@ -1401,7 +1340,6 @@ void __init enable_IR_x2apic(void)
if (!x2apic) {
x2apic = 1;
- apic_ops = &x2apic_ops;
enable_x2apic();
}
@@ -1439,7 +1377,7 @@ end:
return;
}
-#endif /* HAVE_X2APIC */
+#endif /* CONFIG_X86_X2APIC */
#ifdef CONFIG_X86_64
/*
@@ -1570,7 +1508,7 @@ void __init early_init_lapic_mapping(void)
*/
void __init init_apic_mappings(void)
{
-#ifdef HAVE_X2APIC
+#ifdef CONFIG_X86_X2APIC
if (x2apic) {
boot_cpu_physical_apicid = read_apic_id();
return;
@@ -1634,9 +1572,7 @@ int __init APIC_init_uniprocessor(void)
}
#endif
-#ifdef HAVE_X2APIC
enable_IR_x2apic();
-#endif
#ifdef CONFIG_X86_64
default_setup_apic_routing();
#endif
@@ -2021,7 +1957,7 @@ static int lapic_resume(struct sys_device *dev)
local_irq_save(flags);
-#ifdef HAVE_X2APIC
+#ifdef CONFIG_X86_X2APIC
if (x2apic)
enable_x2apic();
else
diff --git a/arch/x86/kernel/genapic_flat_64.c b/arch/x86/kernel/apic/apic_flat_64.c
index 249d2d3c034c..3b002995e145 100644
--- a/arch/x86/kernel/genapic_flat_64.c
+++ b/arch/x86/kernel/apic/apic_flat_64.c
@@ -17,8 +17,8 @@
#include <linux/init.h>
#include <linux/hardirq.h>
#include <asm/smp.h>
+#include <asm/apic.h>
#include <asm/ipi.h>
-#include <asm/genapic.h>
#ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h>
@@ -178,7 +178,7 @@ static int flat_phys_pkg_id(int initial_apic_id, int index_msb)
return hard_smp_processor_id() >> index_msb;
}
-struct genapic apic_flat = {
+struct apic apic_flat = {
.name = "flat",
.probe = NULL,
.acpi_madt_oem_check = flat_acpi_madt_oem_check,
@@ -227,8 +227,14 @@ struct genapic apic_flat = {
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = NULL,
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = NULL,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+ .icr_read = native_apic_icr_read,
+ .icr_write = native_apic_icr_write,
+ .wait_icr_idle = native_apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
};
/*
@@ -321,7 +327,7 @@ physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
return BAD_APICID;
}
-struct genapic apic_physflat = {
+struct apic apic_physflat = {
.name = "physical flat",
.probe = NULL,
@@ -372,6 +378,12 @@ struct genapic apic_physflat = {
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = NULL,
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = NULL,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+ .icr_read = native_apic_icr_read,
+ .icr_write = native_apic_icr_write,
+ .wait_icr_idle = native_apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
};
diff --git a/arch/x86/kernel/bigsmp_32.c b/arch/x86/kernel/apic/bigsmp_32.c
index 47a62f46afdb..0b1093394fdf 100644
--- a/arch/x86/kernel/bigsmp_32.c
+++ b/arch/x86/kernel/apic/bigsmp_32.c
@@ -1,28 +1,26 @@
/*
- * APIC driver for "bigsmp" XAPIC machines with more than 8 virtual CPUs.
+ * APIC driver for "bigsmp" xAPIC machines with more than 8 virtual CPUs.
+ *
* Drives the local APIC in "clustered mode".
*/
-#define APIC_DEFINITION 1
#include <linux/threads.h>
#include <linux/cpumask.h>
-#include <asm/mpspec.h>
-#include <asm/genapic.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <asm/ipi.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/dmi.h>
#include <linux/smp.h>
+#include <asm/apicdef.h>
+#include <asm/fixmap.h>
+#include <asm/mpspec.h>
+#include <asm/apic.h>
+#include <asm/ipi.h>
static inline unsigned bigsmp_get_apic_id(unsigned long x)
{
return (x >> 24) & 0xFF;
}
-#define xapic_phys_to_log_apicid(cpu) (per_cpu(x86_bios_cpu_apicid, cpu))
-
static inline int bigsmp_apic_id_registered(void)
{
return 1;
@@ -37,8 +35,6 @@ static inline const cpumask_t *bigsmp_target_cpus(void)
#endif
}
-#define APIC_DFR_VALUE (APIC_DFR_FLAT)
-
static inline unsigned long
bigsmp_check_apicid_used(physid_mask_t bitmap, int apicid)
{
@@ -53,9 +49,11 @@ static inline unsigned long bigsmp_check_apicid_present(int bit)
static inline unsigned long calculate_ldr(int cpu)
{
unsigned long val, id;
+
val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
- id = xapic_phys_to_log_apicid(cpu);
+ id = per_cpu(x86_bios_cpu_apicid, cpu);
val |= SET_APIC_LOGICAL_ID(id);
+
return val;
}
@@ -71,15 +69,16 @@ static inline void bigsmp_init_apic_ldr(void)
unsigned long val;
int cpu = smp_processor_id();
- apic_write(APIC_DFR, APIC_DFR_VALUE);
+ apic_write(APIC_DFR, APIC_DFR_FLAT);
val = calculate_ldr(cpu);
apic_write(APIC_LDR, val);
}
static inline void bigsmp_setup_apic_routing(void)
{
- printk("Enabling APIC mode: %s. Using %d I/O APICs\n",
- "Physflat", nr_ioapics);
+ printk(KERN_INFO
+ "Enabling APIC mode: Physflat. Using %d I/O APICs\n",
+ nr_ioapics);
}
static inline int bigsmp_apicid_to_node(int logical_apicid)
@@ -100,7 +99,6 @@ static inline physid_mask_t bigsmp_apicid_to_cpu_present(int phys_apicid)
return physid_mask_of_physid(phys_apicid);
}
-extern u8 cpu_2_logical_apicid[];
/* Mapping from cpu number to logical apicid */
static inline int bigsmp_cpu_to_logical_apicid(int cpu)
{
@@ -176,21 +174,24 @@ static int hp_ht_bigsmp(const struct dmi_system_id *d)
{
printk(KERN_NOTICE "%s detected: force use of apic=bigsmp\n", d->ident);
dmi_bigsmp = 1;
+
return 0;
}
static const struct dmi_system_id bigsmp_dmi_table[] = {
{ hp_ht_bigsmp, "HP ProLiant DL760 G2",
- { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
- DMI_MATCH(DMI_BIOS_VERSION, "P44-"),}
+ { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+ DMI_MATCH(DMI_BIOS_VERSION, "P44-"),
+ }
},
{ hp_ht_bigsmp, "HP ProLiant DL740",
- { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
- DMI_MATCH(DMI_BIOS_VERSION, "P47-"),}
+ { DMI_MATCH(DMI_BIOS_VENDOR, "HP"),
+ DMI_MATCH(DMI_BIOS_VERSION, "P47-"),
+ }
},
- { }
+ { } /* NULL entry stops DMI scanning */
};
static void bigsmp_vector_allocation_domain(int cpu, cpumask_t *retmask)
@@ -205,10 +206,11 @@ static int probe_bigsmp(void)
dmi_bigsmp = 1;
else
dmi_check_system(bigsmp_dmi_table);
+
return dmi_bigsmp;
}
-struct genapic apic_bigsmp = {
+struct apic apic_bigsmp = {
.name = "bigsmp",
.probe = probe_bigsmp,
@@ -261,6 +263,12 @@ struct genapic apic_bigsmp = {
.wait_for_init_deassert = default_wait_for_init_deassert,
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = default_inquire_remote_apic,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+ .icr_read = native_apic_icr_read,
+ .icr_write = native_apic_icr_write,
+ .wait_icr_idle = native_apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
};
diff --git a/arch/x86/kernel/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c
index 55515d73d9c2..320f2d2e4e54 100644
--- a/arch/x86/kernel/es7000_32.c
+++ b/arch/x86/kernel/apic/es7000_32.c
@@ -1,10 +1,14 @@
/*
* Written by: Garry Forsgren, Unisys Corporation
* Natalie Protasevich, Unisys Corporation
+ *
* This file contains the code to configure and interface
* with Unisys ES7000 series hardware system manager.
*
- * Copyright (c) 2003 Unisys Corporation. All Rights Reserved.
+ * Copyright (c) 2003 Unisys Corporation.
+ * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar
+ *
+ * All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as
@@ -23,128 +27,105 @@
*
* http://www.unisys.com
*/
-
-#include <linux/module.h>
-#include <linux/types.h>
+#include <linux/notifier.h>
+#include <linux/spinlock.h>
+#include <linux/cpumask.h>
+#include <linux/threads.h>
#include <linux/kernel.h>
-#include <linux/smp.h>
+#include <linux/module.h>
+#include <linux/reboot.h>
#include <linux/string.h>
-#include <linux/spinlock.h>
+#include <linux/types.h>
#include <linux/errno.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
#include <linux/acpi.h>
-#include <asm/io.h>
-#include <asm/nmi.h>
-#include <asm/smp.h>
-#include <asm/atomic.h>
+#include <linux/init.h>
+#include <linux/nmi.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
#include <asm/apicdef.h>
-#include <asm/genapic.h>
+#include <asm/atomic.h>
+#include <asm/fixmap.h>
+#include <asm/mpspec.h>
#include <asm/setup.h>
+#include <asm/apic.h>
+#include <asm/ipi.h>
/*
* ES7000 chipsets
*/
-#define NON_UNISYS 0
-#define ES7000_CLASSIC 1
-#define ES7000_ZORRO 2
+#define NON_UNISYS 0
+#define ES7000_CLASSIC 1
+#define ES7000_ZORRO 2
+#define MIP_REG 1
+#define MIP_PSAI_REG 4
-#define MIP_REG 1
-#define MIP_PSAI_REG 4
+#define MIP_BUSY 1
+#define MIP_SPIN 0xf0000
+#define MIP_VALID 0x0100000000000000ULL
+#define MIP_SW_APIC 0x1020b
-#define MIP_BUSY 1
-#define MIP_SPIN 0xf0000
-#define MIP_VALID 0x0100000000000000ULL
-#define MIP_PORT(VALUE) ((VALUE >> 32) & 0xffff)
+#define MIP_PORT(val) ((val >> 32) & 0xffff)
-#define MIP_RD_LO(VALUE) (VALUE & 0xffffffff)
+#define MIP_RD_LO(val) (val & 0xffffffff)
-struct mip_reg_info {
- unsigned long long mip_info;
- unsigned long long delivery_info;
- unsigned long long host_reg;
- unsigned long long mip_reg;
+struct mip_reg {
+ unsigned long long off_0x00;
+ unsigned long long off_0x08;
+ unsigned long long off_0x10;
+ unsigned long long off_0x18;
+ unsigned long long off_0x20;
+ unsigned long long off_0x28;
+ unsigned long long off_0x30;
+ unsigned long long off_0x38;
};
-struct part_info {
- unsigned char type;
- unsigned char length;
- unsigned char part_id;
- unsigned char apic_mode;
- unsigned long snum;
- char ptype[16];
- char sname[64];
- char pname[64];
+struct mip_reg_info {
+ unsigned long long mip_info;
+ unsigned long long delivery_info;
+ unsigned long long host_reg;
+ unsigned long long mip_reg;
};
struct psai {
- unsigned long long entry_type;
- unsigned long long addr;
- unsigned long long bep_addr;
+ unsigned long long entry_type;
+ unsigned long long addr;
+ unsigned long long bep_addr;
};
-struct es7000_mem_info {
- unsigned char type;
- unsigned char length;
- unsigned char resv[6];
- unsigned long long start;
- unsigned long long size;
-};
+#ifdef CONFIG_ACPI
struct es7000_oem_table {
- unsigned long long hdr;
- struct mip_reg_info mip;
- struct part_info pif;
- struct es7000_mem_info shm;
- struct psai psai;
+ struct acpi_table_header Header;
+ u32 OEMTableAddr;
+ u32 OEMTableSize;
};
-#ifdef CONFIG_ACPI
-
-struct oem_table {
- struct acpi_table_header Header;
- u32 OEMTableAddr;
- u32 OEMTableSize;
-};
+static unsigned long oem_addrX;
+static unsigned long oem_size;
-extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
-extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr);
#endif
-struct mip_reg {
- unsigned long long off_0;
- unsigned long long off_8;
- unsigned long long off_10;
- unsigned long long off_18;
- unsigned long long off_20;
- unsigned long long off_28;
- unsigned long long off_30;
- unsigned long long off_38;
-};
-
-#define MIP_SW_APIC 0x1020b
-#define MIP_FUNC(VALUE) (VALUE & 0xff)
-
/*
* ES7000 Globals
*/
-static volatile unsigned long *psai = NULL;
-static struct mip_reg *mip_reg;
-static struct mip_reg *host_reg;
-static int mip_port;
-static unsigned long mip_addr, host_addr;
+static volatile unsigned long *psai;
+static struct mip_reg *mip_reg;
+static struct mip_reg *host_reg;
+static int mip_port;
+static unsigned long mip_addr;
+static unsigned long host_addr;
-int es7000_plat;
+int es7000_plat;
/*
* GSI override for ES7000 platforms.
*/
-static unsigned int base;
+static unsigned int base;
static int
es7000_rename_gsi(int ioapic, int gsi)
@@ -160,6 +141,7 @@ es7000_rename_gsi(int ioapic, int gsi)
if (!ioapic && (gsi < 16))
gsi += base;
+
return gsi;
}
@@ -181,14 +163,14 @@ static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip)
return 0;
}
-static int __init es7000_update_genapic(void)
+static int __init es7000_update_apic(void)
{
apic->wakeup_cpu = wakeup_secondary_cpu_via_mip;
/* MPENTIUMIII */
if (boot_cpu_data.x86 == 6 &&
(boot_cpu_data.x86_model >= 7 || boot_cpu_data.x86_model <= 11)) {
- es7000_update_genapic_to_cluster();
+ es7000_update_apic_to_cluster();
apic->wait_for_init_deassert = NULL;
apic->wakeup_cpu = wakeup_secondary_cpu_via_mip;
}
@@ -196,8 +178,7 @@ static int __init es7000_update_genapic(void)
return 0;
}
-void __init
-setup_unisys(void)
+static void __init setup_unisys(void)
{
/*
* Determine the generation of the ES7000 currently running.
@@ -212,22 +193,20 @@ setup_unisys(void)
es7000_plat = ES7000_CLASSIC;
ioapic_renumber_irq = es7000_rename_gsi;
- x86_quirks->update_genapic = es7000_update_genapic;
+ x86_quirks->update_apic = es7000_update_apic;
}
/*
- * Parse the OEM Table
+ * Parse the OEM Table:
*/
-
-int __init
-parse_unisys_oem (char *oemptr)
+static int __init parse_unisys_oem(char *oemptr)
{
- int i;
+ int i;
int success = 0;
- unsigned char type, size;
- unsigned long val;
- char *tp = NULL;
- struct psai *psaip = NULL;
+ unsigned char type, size;
+ unsigned long val;
+ char *tp = NULL;
+ struct psai *psaip = NULL;
struct mip_reg_info *mi;
struct mip_reg *host, *mip;
@@ -235,7 +214,7 @@ parse_unisys_oem (char *oemptr)
tp += 8;
- for (i=0; i <= 6; i++) {
+ for (i = 0; i <= 6; i++) {
type = *tp++;
size = *tp++;
tp -= 2;
@@ -273,50 +252,96 @@ parse_unisys_oem (char *oemptr)
tp += size;
}
- if (success < 2) {
+ if (success < 2)
es7000_plat = NON_UNISYS;
- } else
+ else
setup_unisys();
+
return es7000_plat;
}
#ifdef CONFIG_ACPI
-static unsigned long oem_addrX;
-static unsigned long oem_size;
-int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
+static int __init find_unisys_acpi_oem_table(unsigned long *oem_addr)
{
struct acpi_table_header *header = NULL;
- int i = 0;
+ struct es7000_oem_table *table;
acpi_size tbl_size;
+ acpi_status ret;
+ int i = 0;
- while (ACPI_SUCCESS(acpi_get_table_with_size("OEM1", i++, &header, &tbl_size))) {
- if (!memcmp((char *) &header->oem_id, "UNISYS", 6)) {
- struct oem_table *t = (struct oem_table *)header;
+ for (;;) {
+ ret = acpi_get_table_with_size("OEM1", i++, &header, &tbl_size);
+ if (!ACPI_SUCCESS(ret))
+ return -1;
- oem_addrX = t->OEMTableAddr;
- oem_size = t->OEMTableSize;
- early_acpi_os_unmap_memory(header, tbl_size);
+ if (!memcmp((char *) &header->oem_id, "UNISYS", 6))
+ break;
- *oem_addr = (unsigned long)__acpi_map_table(oem_addrX,
- oem_size);
- return 0;
- }
early_acpi_os_unmap_memory(header, tbl_size);
}
- return -1;
+
+ table = (void *)header;
+
+ oem_addrX = table->OEMTableAddr;
+ oem_size = table->OEMTableSize;
+
+ early_acpi_os_unmap_memory(header, tbl_size);
+
+ *oem_addr = (unsigned long)__acpi_map_table(oem_addrX, oem_size);
+
+ return 0;
}
-void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr)
+static void __init unmap_unisys_acpi_oem_table(unsigned long oem_addr)
{
if (!oem_addr)
return;
__acpi_unmap_table((char *)oem_addr, oem_size);
}
-#endif
-static void
-es7000_spin(int n)
+static int es7000_check_dsdt(void)
+{
+ struct acpi_table_header header;
+
+ if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) &&
+ !strncmp(header.oem_id, "UNISYS", 6))
+ return 1;
+ return 0;
+}
+
+/* Hook from generic ACPI tables.c */
+static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+ unsigned long oem_addr = 0;
+ int check_dsdt;
+ int ret = 0;
+
+ /* check dsdt at first to avoid clear fix_map for oem_addr */
+ check_dsdt = es7000_check_dsdt();
+
+ if (!find_unisys_acpi_oem_table(&oem_addr)) {
+ if (check_dsdt) {
+ ret = parse_unisys_oem((char *)oem_addr);
+ } else {
+ setup_unisys();
+ ret = 1;
+ }
+ /*
+ * we need to unmap it
+ */
+ unmap_unisys_acpi_oem_table(oem_addr);
+ }
+ return ret;
+}
+#else /* !CONFIG_ACPI: */
+static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
+{
+ return 0;
+}
+#endif /* !CONFIG_ACPI */
+
+static void es7000_spin(int n)
{
int i = 0;
@@ -327,16 +352,15 @@ es7000_spin(int n)
static int __init
es7000_mip_write(struct mip_reg *mip_reg)
{
- int status = 0;
- int spin;
+ int status = 0;
+ int spin;
spin = MIP_SPIN;
- while (((unsigned long long)host_reg->off_38 &
- (unsigned long long)MIP_VALID) != 0) {
- if (--spin <= 0) {
- printk("es7000_mip_write: Timeout waiting for Host Valid Flag");
- return -1;
- }
+ while ((host_reg->off_0x38 & MIP_VALID) != 0) {
+ if (--spin <= 0) {
+ WARN(1, "Timeout waiting for Host Valid Flag\n");
+ return -1;
+ }
es7000_spin(MIP_SPIN);
}
@@ -345,23 +369,21 @@ es7000_mip_write(struct mip_reg *mip_reg)
spin = MIP_SPIN;
- while (((unsigned long long)mip_reg->off_38 &
- (unsigned long long)MIP_VALID) == 0) {
+ while ((mip_reg->off_0x38 & MIP_VALID) == 0) {
if (--spin <= 0) {
- printk("es7000_mip_write: Timeout waiting for MIP Valid Flag");
+ WARN(1, "Timeout waiting for MIP Valid Flag\n");
return -1;
}
es7000_spin(MIP_SPIN);
}
- status = ((unsigned long long)mip_reg->off_0 &
- (unsigned long long)0xffff0000000000ULL) >> 48;
- mip_reg->off_38 = ((unsigned long long)mip_reg->off_38 &
- (unsigned long long)~MIP_VALID);
+ status = (mip_reg->off_0x00 & 0xffff0000000000ULL) >> 48;
+ mip_reg->off_0x38 &= ~MIP_VALID;
+
return status;
}
-void __init es7000_enable_apic_mode(void)
+static void __init es7000_enable_apic_mode(void)
{
struct mip_reg es7000_mip_reg;
int mip_status;
@@ -369,53 +391,15 @@ void __init es7000_enable_apic_mode(void)
if (!es7000_plat)
return;
- printk("ES7000: Enabling APIC mode.\n");
- memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
- es7000_mip_reg.off_0 = MIP_SW_APIC;
- es7000_mip_reg.off_38 = MIP_VALID;
+ printk(KERN_INFO "ES7000: Enabling APIC mode.\n");
+ memset(&es7000_mip_reg, 0, sizeof(struct mip_reg));
+ es7000_mip_reg.off_0x00 = MIP_SW_APIC;
+ es7000_mip_reg.off_0x38 = MIP_VALID;
- while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0) {
- printk("es7000_enable_apic_mode: command failed, status = %x\n",
- mip_status);
- }
+ while ((mip_status = es7000_mip_write(&es7000_mip_reg)) != 0)
+ WARN(1, "Command failed, status = %x\n", mip_status);
}
-/*
- * APIC driver for the Unisys ES7000 chipset.
- */
-#define APIC_DEFINITION 1
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <asm/mpspec.h>
-#include <asm/genapic.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/acpi.h>
-#include <linux/smp.h>
-#include <asm/ipi.h>
-
-#define APIC_DFR_VALUE_CLUSTER (APIC_DFR_CLUSTER)
-#define INT_DELIVERY_MODE_CLUSTER (dest_LowestPrio)
-#define INT_DEST_MODE_CLUSTER (1) /* logical delivery broadcast to all procs */
-
-#define APIC_DFR_VALUE (APIC_DFR_FLAT)
-
-extern void es7000_enable_apic_mode(void);
-extern int apic_version [MAX_APICS];
-extern u8 cpu_2_logical_apicid[];
-extern unsigned int boot_cpu_physical_apicid;
-
-extern int parse_unisys_oem (char *oemptr);
-extern int find_unisys_acpi_oem_table(unsigned long *oem_addr);
-extern void unmap_unisys_acpi_oem_table(unsigned long oem_addr);
-extern void setup_unisys(void);
-
-#define apicid_cluster(apicid) (apicid & 0xF0)
-#define xapic_phys_to_log_apicid(cpu) per_cpu(x86_bios_cpu_apicid, cpu)
-
static void es7000_vector_allocation_domain(int cpu, cpumask_t *retmask)
{
/* Careful. Some cpus do not strictly honor the set of cpus
@@ -444,18 +428,6 @@ static unsigned int es7000_get_apic_id(unsigned long x)
return (x >> 24) & 0xFF;
}
-#ifdef CONFIG_ACPI
-static int es7000_check_dsdt(void)
-{
- struct acpi_table_header header;
-
- if (ACPI_SUCCESS(acpi_get_table_header(ACPI_SIG_DSDT, 0, &header)) &&
- !strncmp(header.oem_id, "UNISYS", 6))
- return 1;
- return 0;
-}
-#endif
-
static void es7000_send_IPI_mask(const struct cpumask *mask, int vector)
{
default_send_IPI_mask_sequence_phys(mask, vector);
@@ -473,7 +445,7 @@ static void es7000_send_IPI_all(int vector)
static int es7000_apic_id_registered(void)
{
- return 1;
+ return 1;
}
static const cpumask_t *target_cpus_cluster(void)
@@ -498,9 +470,9 @@ static unsigned long es7000_check_apicid_present(int bit)
static unsigned long calculate_ldr(int cpu)
{
- unsigned long id = xapic_phys_to_log_apicid(cpu);
+ unsigned long id = per_cpu(x86_bios_cpu_apicid, cpu);
- return (SET_APIC_LOGICAL_ID(id));
+ return SET_APIC_LOGICAL_ID(id);
}
/*
@@ -515,7 +487,7 @@ static void es7000_init_apic_ldr_cluster(void)
unsigned long val;
int cpu = smp_processor_id();
- apic_write(APIC_DFR, APIC_DFR_VALUE_CLUSTER);
+ apic_write(APIC_DFR, APIC_DFR_CLUSTER);
val = calculate_ldr(cpu);
apic_write(APIC_LDR, val);
}
@@ -525,7 +497,7 @@ static void es7000_init_apic_ldr(void)
unsigned long val;
int cpu = smp_processor_id();
- apic_write(APIC_DFR, APIC_DFR_VALUE);
+ apic_write(APIC_DFR, APIC_DFR_FLAT);
val = calculate_ldr(cpu);
apic_write(APIC_LDR, val);
}
@@ -533,10 +505,12 @@ static void es7000_init_apic_ldr(void)
static void es7000_setup_apic_routing(void)
{
int apic = per_cpu(x86_bios_cpu_apicid, smp_processor_id());
- printk("Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
+
+ printk(KERN_INFO
+ "Enabling APIC mode: %s. Using %d I/O APICs, target cpus %lx\n",
(apic_version[apic] == 0x14) ?
"Physical Cluster" : "Logical Cluster",
- nr_ioapics, cpus_addr(*es7000_target_cpus())[0]);
+ nr_ioapics, cpus_addr(*es7000_target_cpus())[0]);
}
static int es7000_apicid_to_node(int logical_apicid)
@@ -550,18 +524,19 @@ static int es7000_cpu_present_to_apicid(int mps_cpu)
if (!mps_cpu)
return boot_cpu_physical_apicid;
else if (mps_cpu < nr_cpu_ids)
- return (int) per_cpu(x86_bios_cpu_apicid, mps_cpu);
+ return per_cpu(x86_bios_cpu_apicid, mps_cpu);
else
return BAD_APICID;
}
+static int cpu_id;
+
static physid_mask_t es7000_apicid_to_cpu_present(int phys_apicid)
{
- static int id = 0;
physid_mask_t mask;
- mask = physid_mask_of_physid(id);
- ++id;
+ mask = physid_mask_of_physid(cpu_id);
+ ++cpu_id;
return mask;
}
@@ -572,7 +547,7 @@ static int es7000_cpu_to_logical_apicid(int cpu)
#ifdef CONFIG_SMP
if (cpu >= nr_cpu_ids)
return BAD_APICID;
- return (int)cpu_2_logical_apicid[cpu];
+ return cpu_2_logical_apicid[cpu];
#else
return logical_smp_processor_id();
#endif
@@ -587,7 +562,7 @@ static physid_mask_t es7000_ioapic_phys_id_map(physid_mask_t phys_map)
static int es7000_check_phys_apicid_present(int cpu_physical_apicid)
{
boot_cpu_physical_apicid = read_apic_id();
- return (1);
+ return 1;
}
static unsigned int
@@ -613,9 +588,8 @@ es7000_cpu_mask_to_apicid_cluster(const struct cpumask *cpumask)
if (cpumask_test_cpu(cpu, cpumask)) {
int new_apicid = es7000_cpu_to_logical_apicid(cpu);
- if (apicid_cluster(apicid) !=
- apicid_cluster(new_apicid)) {
- printk ("%s: Not a valid mask!\n", __func__);
+ if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
+ WARN(1, "Not a valid mask!");
return 0xFF;
}
@@ -648,9 +622,8 @@ static unsigned int es7000_cpu_mask_to_apicid(const cpumask_t *cpumask)
if (cpu_isset(cpu, *cpumask)) {
int new_apicid = es7000_cpu_to_logical_apicid(cpu);
- if (apicid_cluster(apicid) !=
- apicid_cluster(new_apicid)) {
- printk ("%s: Not a valid mask!\n", __func__);
+ if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
+ printk("%s: Not a valid mask!\n", __func__);
return es7000_cpu_to_logical_apicid(0);
}
@@ -686,11 +659,12 @@ static int es7000_phys_pkg_id(int cpuid_apic, int index_msb)
return cpuid_apic >> index_msb;
}
-void __init es7000_update_genapic_to_cluster(void)
+void __init es7000_update_apic_to_cluster(void)
{
apic->target_cpus = target_cpus_cluster;
- apic->irq_delivery_mode = INT_DELIVERY_MODE_CLUSTER;
- apic->irq_dest_mode = INT_DEST_MODE_CLUSTER;
+ apic->irq_delivery_mode = dest_LowestPrio;
+ /* logical delivery broadcast to all procs: */
+ apic->irq_dest_mode = 1;
apic->init_apic_ldr = es7000_init_apic_ldr_cluster;
@@ -716,40 +690,8 @@ es7000_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
return 0;
}
-#ifdef CONFIG_ACPI
-/* Hook from generic ACPI tables.c */
-static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
-{
- unsigned long oem_addr = 0;
- int check_dsdt;
- int ret = 0;
-
- /* check dsdt at first to avoid clear fix_map for oem_addr */
- check_dsdt = es7000_check_dsdt();
-
- if (!find_unisys_acpi_oem_table(&oem_addr)) {
- if (check_dsdt)
- ret = parse_unisys_oem((char *)oem_addr);
- else {
- setup_unisys();
- ret = 1;
- }
- /*
- * we need to unmap it
- */
- unmap_unisys_acpi_oem_table(oem_addr);
- }
- return ret;
-}
-#else
-static int __init es7000_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
-{
- return 0;
-}
-#endif
-
-struct genapic apic_es7000 = {
+struct apic apic_es7000 = {
.name = "es7000",
.probe = probe_es7000,
@@ -804,6 +746,12 @@ struct genapic apic_es7000 = {
/* Nothing to do for most platforms, since cleared by the INIT cycle: */
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = default_inquire_remote_apic,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+ .icr_read = native_apic_icr_read,
+ .icr_write = native_apic_icr_write,
+ .wait_icr_idle = native_apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
};
diff --git a/arch/x86/kernel/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index a89878e08a42..00e6071cefc4 100644
--- a/arch/x86/kernel/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -62,7 +62,7 @@
#include <asm/uv/uv_hub.h>
#include <asm/uv/uv_irq.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
#define __apicdebuginit(type) static type __init
diff --git a/arch/x86/kernel/ipi.c b/arch/x86/kernel/apic/ipi.c
index dbf5445727a9..dbf5445727a9 100644
--- a/arch/x86/kernel/ipi.c
+++ b/arch/x86/kernel/apic/ipi.c
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/apic/nmi.c
index bdfad80c3cf1..bdfad80c3cf1 100644
--- a/arch/x86/kernel/nmi.c
+++ b/arch/x86/kernel/apic/nmi.c
diff --git a/arch/x86/kernel/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c
index 0cc41a1d2550..d9d6d61eed82 100644
--- a/arch/x86/kernel/numaq_32.c
+++ b/arch/x86/kernel/apic/numaq_32.c
@@ -2,6 +2,7 @@
* Written by: Patricia Gaughen, IBM Corporation
*
* Copyright (C) 2002, IBM Corp.
+ * Copyright (C) 2009, Red Hat, Inc., Ingo Molnar
*
* All rights reserved.
*
@@ -22,21 +23,81 @@
*
* Send feedback to <gone@us.ibm.com>
*/
-
#include <linux/nodemask.h>
+#include <linux/topology.h>
#include <linux/bootmem.h>
+#include <linux/threads.h>
+#include <linux/cpumask.h>
+#include <linux/kernel.h>
#include <linux/mmzone.h>
#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/numa.h>
+#include <linux/smp.h>
+#include <linux/io.h>
#include <linux/mm.h>
#include <asm/processor.h>
-#include <asm/topology.h>
-#include <asm/genapic.h>
+#include <asm/fixmap.h>
+#include <asm/mpspec.h>
#include <asm/numaq.h>
#include <asm/setup.h>
+#include <asm/apic.h>
#include <asm/e820.h>
+#include <asm/ipi.h>
+
+#define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
+
+int found_numaq;
+
+/*
+ * Have to match translation table entries to main table entries by counter
+ * hence the mpc_record variable .... can't see a less disgusting way of
+ * doing this ....
+ */
+struct mpc_trans {
+ unsigned char mpc_type;
+ unsigned char trans_len;
+ unsigned char trans_type;
+ unsigned char trans_quad;
+ unsigned char trans_global;
+ unsigned char trans_local;
+ unsigned short trans_reserved;
+};
+
+/* x86_quirks member */
+static int mpc_record;
+
+static __cpuinitdata struct mpc_trans *translation_table[MAX_MPC_ENTRY];
+
+int mp_bus_id_to_node[MAX_MP_BUSSES];
+int mp_bus_id_to_local[MAX_MP_BUSSES];
+int quad_local_to_mp_bus_id[NR_CPUS/4][4];
+
-#define MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
+static inline void numaq_register_node(int node, struct sys_cfg_data *scd)
+{
+ struct eachquadmem *eq = scd->eq + node;
+
+ node_set_online(node);
+
+ /* Convert to pages */
+ node_start_pfn[node] =
+ MB_TO_PAGES(eq->hi_shrd_mem_start - eq->priv_mem_size);
+
+ node_end_pfn[node] =
+ MB_TO_PAGES(eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
+
+ e820_register_active_regions(node, node_start_pfn[node],
+ node_end_pfn[node]);
+
+ memory_present(node, node_start_pfn[node], node_end_pfn[node]);
+
+ node_remap_size[node] = node_memmap_size_bytes(node,
+ node_start_pfn[node],
+ node_end_pfn[node]);
+}
/*
* Function: smp_dump_qct()
@@ -46,34 +107,18 @@
*/
static void __init smp_dump_qct(void)
{
+ struct sys_cfg_data *scd;
int node;
- struct eachquadmem *eq;
- struct sys_cfg_data *scd =
- (struct sys_cfg_data *)__va(SYS_CFG_DATA_PRIV_ADDR);
+
+ scd = (void *)__va(SYS_CFG_DATA_PRIV_ADDR);
nodes_clear(node_online_map);
for_each_node(node) {
- if (scd->quads_present31_0 & (1 << node)) {
- node_set_online(node);
- eq = &scd->eq[node];
- /* Convert to pages */
- node_start_pfn[node] = MB_TO_PAGES(
- eq->hi_shrd_mem_start - eq->priv_mem_size);
- node_end_pfn[node] = MB_TO_PAGES(
- eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
-
- e820_register_active_regions(node, node_start_pfn[node],
- node_end_pfn[node]);
- memory_present(node,
- node_start_pfn[node], node_end_pfn[node]);
- node_remap_size[node] = node_memmap_size_bytes(node,
- node_start_pfn[node],
- node_end_pfn[node]);
- }
+ if (scd->quads_present31_0 & (1 << node))
+ numaq_register_node(node, scd);
}
}
-
void __cpuinit numaq_tsc_disable(void)
{
if (!found_numaq)
@@ -91,28 +136,6 @@ static int __init numaq_pre_time_init(void)
return 0;
}
-int found_numaq;
-
-/*
- * Have to match translation table entries to main table entries by counter
- * hence the mpc_record variable .... can't see a less disgusting way of
- * doing this ....
- */
-struct mpc_config_translation {
- unsigned char mpc_type;
- unsigned char trans_len;
- unsigned char trans_type;
- unsigned char trans_quad;
- unsigned char trans_global;
- unsigned char trans_local;
- unsigned short trans_reserved;
-};
-
-/* x86_quirks member */
-static int mpc_record;
-static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY]
- __cpuinitdata;
-
static inline int generate_logical_apicid(int quad, int phys_apicid)
{
return (quad << 4) + (phys_apicid ? phys_apicid << 1 : 1);
@@ -124,17 +147,15 @@ static int mpc_apic_id(struct mpc_cpu *m)
int quad = translation_table[mpc_record]->trans_quad;
int logical_apicid = generate_logical_apicid(quad, m->apicid);
- printk(KERN_DEBUG "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
- m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8,
- (m->cpufeature & CPU_MODEL_MASK) >> 4,
- m->apicver, quad, logical_apicid);
+ printk(KERN_DEBUG
+ "Processor #%d %u:%u APIC version %d (quad %d, apic %d)\n",
+ m->apicid, (m->cpufeature & CPU_FAMILY_MASK) >> 8,
+ (m->cpufeature & CPU_MODEL_MASK) >> 4,
+ m->apicver, quad, logical_apicid);
+
return logical_apicid;
}
-int mp_bus_id_to_node[MAX_MP_BUSSES];
-
-int mp_bus_id_to_local[MAX_MP_BUSSES];
-
/* x86_quirks member */
static void mpc_oem_bus_info(struct mpc_bus *m, char *name)
{
@@ -143,11 +164,9 @@ static void mpc_oem_bus_info(struct mpc_bus *m, char *name)
mp_bus_id_to_node[m->busid] = quad;
mp_bus_id_to_local[m->busid] = local;
- printk(KERN_INFO "Bus #%d is %s (node %d)\n",
- m->busid, name, quad);
-}
-int quad_local_to_mp_bus_id [NR_CPUS/4][4];
+ printk(KERN_INFO "Bus #%d is %s (node %d)\n", m->busid, name, quad);
+}
/* x86_quirks member */
static void mpc_oem_pci_bus(struct mpc_bus *m)
@@ -158,17 +177,18 @@ static void mpc_oem_pci_bus(struct mpc_bus *m)
quad_local_to_mp_bus_id[quad][local] = m->busid;
}
-static void __init MP_translation_info(struct mpc_config_translation *m)
+static void __init MP_translation_info(struct mpc_trans *m)
{
printk(KERN_INFO
- "Translation: record %d, type %d, quad %d, global %d, local %d\n",
+ "Translation: record %d, type %d, quad %d, global %d, local %d\n",
mpc_record, m->trans_type, m->trans_quad, m->trans_global,
m->trans_local);
if (mpc_record >= MAX_MPC_ENTRY)
printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
else
- translation_table[mpc_record] = m; /* stash this for later */
+ translation_table[mpc_record] = m; /* stash this for later */
+
if (m->trans_quad < MAX_NUMNODES && !node_online(m->trans_quad))
node_set_online(m->trans_quad);
}
@@ -186,16 +206,16 @@ static int __init mpf_checksum(unsigned char *mp, int len)
/*
* Read/parse the MPC oem tables
*/
-
-static void __init smp_read_mpc_oem(struct mpc_oemtable *oemtable,
- unsigned short oemsize)
+static void __init
+ smp_read_mpc_oem(struct mpc_oemtable *oemtable, unsigned short oemsize)
{
int count = sizeof(*oemtable); /* the header size */
unsigned char *oemptr = ((unsigned char *)oemtable) + count;
mpc_record = 0;
- printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n",
- oemtable);
+ printk(KERN_INFO
+ "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
+
if (memcmp(oemtable->signature, MPC_OEM_SIGNATURE, 4)) {
printk(KERN_WARNING
"SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
@@ -203,16 +223,18 @@ static void __init smp_read_mpc_oem(struct mpc_oemtable *oemtable,
oemtable->signature[2], oemtable->signature[3]);
return;
}
+
if (mpf_checksum((unsigned char *)oemtable, oemtable->length)) {
printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
return;
}
+
while (count < oemtable->length) {
switch (*oemptr) {
case MP_TRANSLATION:
{
- struct mpc_config_translation *m =
- (struct mpc_config_translation *)oemptr;
+ struct mpc_trans *m = (void *)oemptr;
+
MP_translation_info(m);
oemptr += sizeof(*m);
count += sizeof(*m);
@@ -220,12 +242,10 @@ static void __init smp_read_mpc_oem(struct mpc_oemtable *oemtable,
break;
}
default:
- {
- printk(KERN_WARNING
- "Unrecognised OEM table entry type! - %d\n",
- (int)*oemptr);
- return;
- }
+ printk(KERN_WARNING
+ "Unrecognised OEM table entry type! - %d\n",
+ (int)*oemptr);
+ return;
}
}
}
@@ -236,7 +256,7 @@ static int __init numaq_setup_ioapic_ids(void)
return 1;
}
-static int __init numaq_update_genapic(void)
+static int __init numaq_update_apic(void)
{
apic->wakeup_cpu = wakeup_secondary_cpu_via_nmi;
@@ -244,37 +264,30 @@ static int __init numaq_update_genapic(void)
}
static struct x86_quirks numaq_x86_quirks __initdata = {
- .arch_pre_time_init = numaq_pre_time_init,
- .arch_time_init = NULL,
- .arch_pre_intr_init = NULL,
- .arch_memory_setup = NULL,
- .arch_intr_init = NULL,
- .arch_trap_init = NULL,
- .mach_get_smp_config = NULL,
- .mach_find_smp_config = NULL,
- .mpc_record = &mpc_record,
- .mpc_apic_id = mpc_apic_id,
- .mpc_oem_bus_info = mpc_oem_bus_info,
- .mpc_oem_pci_bus = mpc_oem_pci_bus,
- .smp_read_mpc_oem = smp_read_mpc_oem,
- .setup_ioapic_ids = numaq_setup_ioapic_ids,
- .update_genapic = numaq_update_genapic,
+ .arch_pre_time_init = numaq_pre_time_init,
+ .arch_time_init = NULL,
+ .arch_pre_intr_init = NULL,
+ .arch_memory_setup = NULL,
+ .arch_intr_init = NULL,
+ .arch_trap_init = NULL,
+ .mach_get_smp_config = NULL,
+ .mach_find_smp_config = NULL,
+ .mpc_record = &mpc_record,
+ .mpc_apic_id = mpc_apic_id,
+ .mpc_oem_bus_info = mpc_oem_bus_info,
+ .mpc_oem_pci_bus = mpc_oem_pci_bus,
+ .smp_read_mpc_oem = smp_read_mpc_oem,
+ .setup_ioapic_ids = numaq_setup_ioapic_ids,
+ .update_apic = numaq_update_apic,
};
-void numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
-{
- if (strncmp(oem, "IBM NUMA", 8))
- printk("Warning! Not a NUMA-Q system!\n");
- else
- found_numaq = 1;
-}
-
static __init void early_check_numaq(void)
{
/*
* Find possible boot-time SMP configuration:
*/
early_find_smp_config();
+
/*
* get boot-time SMP configuration:
*/
@@ -291,30 +304,10 @@ int __init get_memcfg_numaq(void)
if (!found_numaq)
return 0;
smp_dump_qct();
+
return 1;
}
-/*
- * APIC driver for the IBM NUMAQ chipset.
- */
-#define APIC_DEFINITION 1
-#include <linux/threads.h>
-#include <linux/cpumask.h>
-#include <asm/mpspec.h>
-#include <asm/genapic.h>
-#include <asm/fixmap.h>
-#include <asm/apicdef.h>
-#include <asm/ipi.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/numa.h>
-#include <linux/smp.h>
-#include <asm/numaq.h>
-#include <asm/io.h>
-#include <linux/mmzone.h>
-#include <linux/nodemask.h>
-
#define NUMAQ_APIC_DFR_VALUE (APIC_DFR_CLUSTER)
static inline unsigned int numaq_get_apic_id(unsigned long x)
@@ -337,10 +330,8 @@ static inline void numaq_send_IPI_all(int vector)
numaq_send_IPI_mask(cpu_online_mask, vector);
}
-extern void numaq_mps_oem_check(struct mpc_table *, char *, char *);
-
-#define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8)
-#define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa)
+#define NUMAQ_TRAMPOLINE_PHYS_LOW (0x8)
+#define NUMAQ_TRAMPOLINE_PHYS_HIGH (0xa)
/*
* Because we use NMIs rather than the INIT-STARTUP sequence to
@@ -351,16 +342,6 @@ static inline void numaq_smp_callin_clear_local_apic(void)
clear_local_APIC();
}
-static inline void
-numaq_store_NMI_vector(unsigned short *high, unsigned short *low)
-{
- printk("Storing NMI vector\n");
- *high =
- *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_HIGH));
- *low =
- *((volatile unsigned short *)phys_to_virt(NUMAQ_TRAMPOLINE_PHYS_LOW));
-}
-
static inline const cpumask_t *numaq_target_cpus(void)
{
return &CPU_MASK_ALL;
@@ -377,8 +358,6 @@ static inline unsigned long numaq_check_apicid_present(int bit)
return physid_isset(bit, phys_cpu_present_map);
}
-#define apicid_cluster(apicid) (apicid & 0xF0)
-
static inline int numaq_apic_id_registered(void)
{
return 1;
@@ -391,8 +370,9 @@ static inline void numaq_init_apic_ldr(void)
static inline void numaq_setup_apic_routing(void)
{
- printk("Enabling APIC mode: %s. Using %d I/O APICs\n",
- "NUMA-Q", nr_ioapics);
+ printk(KERN_INFO
+ "Enabling APIC mode: NUMA-Q. Using %d I/O APICs\n",
+ nr_ioapics);
}
/*
@@ -410,14 +390,11 @@ static inline physid_mask_t numaq_ioapic_phys_id_map(physid_mask_t phys_map)
return physids_promote(0xFUL);
}
-/* Mapping from cpu number to logical apicid */
-extern u8 cpu_2_logical_apicid[];
-
static inline int numaq_cpu_to_logical_apicid(int cpu)
{
if (cpu >= nr_cpu_ids)
return BAD_APICID;
- return (int)cpu_2_logical_apicid[cpu];
+ return cpu_2_logical_apicid[cpu];
}
/*
@@ -433,7 +410,7 @@ static inline int numaq_cpu_present_to_apicid(int mps_cpu)
return BAD_APICID;
}
-static inline int numaq_apicid_to_node(int logical_apicid)
+static inline int numaq_apicid_to_node(int logical_apicid)
{
return logical_apicid >> 4;
}
@@ -475,9 +452,15 @@ static inline int numaq_phys_pkg_id(int cpuid_apic, int index_msb)
{
return cpuid_apic >> index_msb;
}
-static int __numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
+
+static int
+numaq_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
{
- numaq_mps_oem_check(mpc, oem, productid);
+ if (strncmp(oem, "IBM NUMA", 8))
+ printk(KERN_ERR "Warning! Not a NUMA-Q system!\n");
+ else
+ found_numaq = 1;
+
return found_numaq;
}
@@ -507,13 +490,17 @@ static void numaq_setup_portio_remap(void)
if (num_quads <= 1)
return;
- printk("Remapping cross-quad port I/O for %d quads\n", num_quads);
+ printk(KERN_INFO
+ "Remapping cross-quad port I/O for %d quads\n", num_quads);
+
xquad_portio = ioremap(XQUAD_PORTIO_BASE, num_quads*XQUAD_PORTIO_QUAD);
- printk("xquad_portio vaddr 0x%08lx, len %08lx\n",
+
+ printk(KERN_INFO
+ "xquad_portio vaddr 0x%08lx, len %08lx\n",
(u_long) xquad_portio, (u_long) num_quads*XQUAD_PORTIO_QUAD);
}
-struct genapic apic_numaq = {
+struct apic apic_numaq = {
.name = "NUMAQ",
.probe = probe_numaq,
@@ -544,7 +531,7 @@ struct genapic apic_numaq = {
.check_phys_apicid_present = numaq_check_phys_apicid_present,
.enable_apic_mode = NULL,
.phys_pkg_id = numaq_phys_pkg_id,
- .mps_oem_check = __numaq_mps_oem_check,
+ .mps_oem_check = numaq_mps_oem_check,
.get_apic_id = numaq_get_apic_id,
.set_apic_id = NULL,
@@ -567,6 +554,12 @@ struct genapic apic_numaq = {
.wait_for_init_deassert = NULL,
.smp_callin_clear_local_apic = numaq_smp_callin_clear_local_apic,
- .store_NMI_vector = numaq_store_NMI_vector,
.inquire_remote_apic = NULL,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+ .icr_read = native_apic_icr_read,
+ .icr_write = native_apic_icr_write,
+ .wait_icr_idle = native_apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
};
diff --git a/arch/x86/kernel/probe_32.c b/arch/x86/kernel/apic/probe_32.c
index 22337b75de62..3a730fa574bb 100644
--- a/arch/x86/kernel/probe_32.c
+++ b/arch/x86/kernel/apic/probe_32.c
@@ -8,6 +8,7 @@
*/
#include <linux/threads.h>
#include <linux/cpumask.h>
+#include <linux/module.h>
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/ctype.h>
@@ -16,32 +17,27 @@
#include <asm/fixmap.h>
#include <asm/mpspec.h>
#include <asm/apicdef.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
#include <asm/setup.h>
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <asm/mpspec.h>
-#include <asm/genapic.h>
#include <asm/fixmap.h>
#include <asm/apicdef.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/smp.h>
#include <linux/init.h>
-#include <asm/genapic.h>
#include <asm/ipi.h>
#include <linux/smp.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/acpi.h>
-#include <asm/arch_hooks.h>
#include <asm/e820.h>
#include <asm/setup.h>
-#include <asm/genapic.h>
-
#ifdef CONFIG_HOTPLUG_CPU
#define DEFAULT_SEND_IPI (1)
#else
@@ -50,7 +46,31 @@
int no_broadcast = DEFAULT_SEND_IPI;
-#ifdef CONFIG_X86_LOCAL_APIC
+static __init int no_ipi_broadcast(char *str)
+{
+ get_option(&str, &no_broadcast);
+ pr_info("Using %s mode\n",
+ no_broadcast ? "No IPI Broadcast" : "IPI Broadcast");
+ return 1;
+}
+__setup("no_ipi_broadcast=", no_ipi_broadcast);
+
+static int __init print_ipi_mode(void)
+{
+ pr_info("Using IPI %s mode\n",
+ no_broadcast ? "No-Shortcut" : "Shortcut");
+ return 0;
+}
+late_initcall(print_ipi_mode);
+
+void default_setup_apic_routing(void)
+{
+#ifdef CONFIG_X86_IO_APIC
+ printk(KERN_INFO
+ "Enabling APIC mode: Flat. Using %d I/O APICs\n",
+ nr_ioapics);
+#endif
+}
static void default_vector_allocation_domain(int cpu, struct cpumask *retmask)
{
@@ -72,7 +92,7 @@ static int probe_default(void)
return 1;
}
-struct genapic apic_default = {
+struct apic apic_default = {
.name = "default",
.probe = probe_default,
@@ -125,19 +145,26 @@ struct genapic apic_default = {
.wait_for_init_deassert = default_wait_for_init_deassert,
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = default_inquire_remote_apic,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+ .icr_read = native_apic_icr_read,
+ .icr_write = native_apic_icr_write,
+ .wait_icr_idle = native_apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
};
-extern struct genapic apic_numaq;
-extern struct genapic apic_summit;
-extern struct genapic apic_bigsmp;
-extern struct genapic apic_es7000;
-extern struct genapic apic_default;
+extern struct apic apic_numaq;
+extern struct apic apic_summit;
+extern struct apic apic_bigsmp;
+extern struct apic apic_es7000;
+extern struct apic apic_default;
-struct genapic *apic = &apic_default;
+struct apic *apic = &apic_default;
+EXPORT_SYMBOL_GPL(apic);
-static struct genapic *apic_probe[] __initdata = {
+static struct apic *apic_probe[] __initdata = {
#ifdef CONFIG_X86_NUMAQ
&apic_numaq,
#endif
@@ -170,8 +197,8 @@ static int __init parse_apic(char *arg)
}
}
- if (x86_quirks->update_genapic)
- x86_quirks->update_genapic();
+ if (x86_quirks->update_apic)
+ x86_quirks->update_apic();
/* Parsed again by __setup for debug/verbose */
return 0;
@@ -191,8 +218,8 @@ void __init generic_bigsmp_probe(void)
if (!cmdline_apic && apic == &apic_default) {
if (apic_bigsmp.probe()) {
apic = &apic_bigsmp;
- if (x86_quirks->update_genapic)
- x86_quirks->update_genapic();
+ if (x86_quirks->update_apic)
+ x86_quirks->update_apic();
printk(KERN_INFO "Overriding APIC driver with %s\n",
apic->name);
}
@@ -214,8 +241,8 @@ void __init generic_apic_probe(void)
if (!apic_probe[i])
panic("Didn't find an APIC driver");
- if (x86_quirks->update_genapic)
- x86_quirks->update_genapic();
+ if (x86_quirks->update_apic)
+ x86_quirks->update_apic();
}
printk(KERN_INFO "Using APIC driver %s\n", apic->name);
}
@@ -235,8 +262,8 @@ generic_mps_oem_check(struct mpc_table *mpc, char *oem, char *productid)
if (!cmdline_apic) {
apic = apic_probe[i];
- if (x86_quirks->update_genapic)
- x86_quirks->update_genapic();
+ if (x86_quirks->update_apic)
+ x86_quirks->update_apic();
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
apic->name);
}
@@ -257,8 +284,8 @@ int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
if (!cmdline_apic) {
apic = apic_probe[i];
- if (x86_quirks->update_genapic)
- x86_quirks->update_genapic();
+ if (x86_quirks->update_apic)
+ x86_quirks->update_apic();
printk(KERN_INFO "Switched to APIC driver `%s'.\n",
apic->name);
}
@@ -266,146 +293,3 @@ int __init default_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
}
return 0;
}
-
-#endif /* CONFIG_X86_LOCAL_APIC */
-
-/**
- * pre_intr_init_hook - initialisation prior to setting up interrupt vectors
- *
- * Description:
- * Perform any necessary interrupt initialisation prior to setting up
- * the "ordinary" interrupt call gates. For legacy reasons, the ISA
- * interrupts should be initialised here if the machine emulates a PC
- * in any way.
- **/
-void __init pre_intr_init_hook(void)
-{
- if (x86_quirks->arch_pre_intr_init) {
- if (x86_quirks->arch_pre_intr_init())
- return;
- }
- init_ISA_irqs();
-}
-
-/**
- * intr_init_hook - post gate setup interrupt initialisation
- *
- * Description:
- * Fill in any interrupts that may have been left out by the general
- * init_IRQ() routine. interrupts having to do with the machine rather
- * than the devices on the I/O bus (like APIC interrupts in intel MP
- * systems) are started here.
- **/
-void __init intr_init_hook(void)
-{
- if (x86_quirks->arch_intr_init) {
- if (x86_quirks->arch_intr_init())
- return;
- }
-}
-
-/**
- * pre_setup_arch_hook - hook called prior to any setup_arch() execution
- *
- * Description:
- * generally used to activate any machine specific identification
- * routines that may be needed before setup_arch() runs. On Voyager
- * this is used to get the board revision and type.
- **/
-void __init pre_setup_arch_hook(void)
-{
-}
-
-/**
- * trap_init_hook - initialise system specific traps
- *
- * Description:
- * Called as the final act of trap_init(). Used in VISWS to initialise
- * the various board specific APIC traps.
- **/
-void __init trap_init_hook(void)
-{
- if (x86_quirks->arch_trap_init) {
- if (x86_quirks->arch_trap_init())
- return;
- }
-}
-
-static struct irqaction irq0 = {
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
- .mask = CPU_MASK_NONE,
- .name = "timer"
-};
-
-/**
- * pre_time_init_hook - do any specific initialisations before.
- *
- **/
-void __init pre_time_init_hook(void)
-{
- if (x86_quirks->arch_pre_time_init)
- x86_quirks->arch_pre_time_init();
-}
-
-/**
- * time_init_hook - do any specific initialisations for the system timer.
- *
- * Description:
- * Must plug the system timer interrupt source at HZ into the IRQ listed
- * in irq_vectors.h:TIMER_IRQ
- **/
-void __init time_init_hook(void)
-{
- if (x86_quirks->arch_time_init) {
- /*
- * A nonzero return code does not mean failure, it means
- * that the architecture quirk does not want any
- * generic (timer) setup to be performed after this:
- */
- if (x86_quirks->arch_time_init())
- return;
- }
-
- irq0.mask = cpumask_of_cpu(0);
- setup_irq(0, &irq0);
-}
-
-#ifdef CONFIG_MCA
-/**
- * mca_nmi_hook - hook into MCA specific NMI chain
- *
- * Description:
- * The MCA (Microchannel Architecture) has an NMI chain for NMI sources
- * along the MCA bus. Use this to hook into that chain if you will need
- * it.
- **/
-void mca_nmi_hook(void)
-{
- /*
- * If I recall correctly, there's a whole bunch of other things that
- * we can do to check for NMI problems, but that's all I know about
- * at the moment.
- */
- pr_warning("NMI generated from unknown source!\n");
-}
-#endif
-
-static __init int no_ipi_broadcast(char *str)
-{
- get_option(&str, &no_broadcast);
- pr_info("Using %s mode\n",
- no_broadcast ? "No IPI Broadcast" : "IPI Broadcast");
- return 1;
-}
-__setup("no_ipi_broadcast=", no_ipi_broadcast);
-
-static int __init print_ipi_mode(void)
-{
- pr_info("Using IPI %s mode\n",
- no_broadcast ? "No-Shortcut" : "Shortcut");
- return 0;
-}
-
-late_initcall(print_ipi_mode);
-
diff --git a/arch/x86/kernel/genapic_64.c b/arch/x86/kernel/apic/probe_64.c
index 820dea5d0ebe..e7c163661c77 100644
--- a/arch/x86/kernel/genapic_64.c
+++ b/arch/x86/kernel/apic/probe_64.c
@@ -19,24 +19,27 @@
#include <linux/dmar.h>
#include <asm/smp.h>
+#include <asm/apic.h>
#include <asm/ipi.h>
-#include <asm/genapic.h>
#include <asm/setup.h>
-extern struct genapic apic_flat;
-extern struct genapic apic_physflat;
-extern struct genapic apic_x2xpic_uv_x;
-extern struct genapic apic_x2apic_phys;
-extern struct genapic apic_x2apic_cluster;
+extern struct apic apic_flat;
+extern struct apic apic_physflat;
+extern struct apic apic_x2xpic_uv_x;
+extern struct apic apic_x2apic_phys;
+extern struct apic apic_x2apic_cluster;
-struct genapic __read_mostly *apic = &apic_flat;
+struct apic __read_mostly *apic = &apic_flat;
+EXPORT_SYMBOL_GPL(apic);
-static struct genapic *apic_probe[] __initdata = {
+static struct apic *apic_probe[] __initdata = {
#ifdef CONFIG_X86_UV
&apic_x2apic_uv_x,
#endif
+#ifdef CONFIG_X86_X2APIC
&apic_x2apic_phys,
&apic_x2apic_cluster,
+#endif
&apic_physflat,
NULL,
};
@@ -46,10 +49,19 @@ static struct genapic *apic_probe[] __initdata = {
*/
void __init default_setup_apic_routing(void)
{
- if (apic == &apic_x2apic_phys || apic == &apic_x2apic_cluster) {
- if (!intr_remapping_enabled)
- apic = &apic_flat;
+#ifdef CONFIG_X86_X2APIC
+ if (x2apic && (apic != &apic_x2apic_phys &&
+#ifdef CONFIG_X86_UV
+ apic != &apic_x2apic_uv_x &&
+#endif
+ apic != &apic_x2apic_cluster)) {
+ if (x2apic_phys)
+ apic = &apic_x2apic_phys;
+ else
+ apic = &apic_x2apic_cluster;
+ printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
}
+#endif
if (apic == &apic_flat) {
if (max_physical_apicid >= 8)
@@ -57,8 +69,8 @@ void __init default_setup_apic_routing(void)
printk(KERN_INFO "Setting APIC routing to %s\n", apic->name);
}
- if (x86_quirks->update_genapic)
- x86_quirks->update_genapic();
+ if (x86_quirks->update_apic)
+ x86_quirks->update_apic();
}
/* Same for both flat and physical. */
diff --git a/arch/x86/kernel/summit_32.c b/arch/x86/kernel/apic/summit_32.c
index 1e733eff9b33..cfe7b09015d8 100644
--- a/arch/x86/kernel/summit_32.c
+++ b/arch/x86/kernel/apic/summit_32.c
@@ -34,13 +34,11 @@
/*
* APIC driver for the IBM "Summit" chipset.
*/
-#define APIC_DEFINITION 1
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <asm/mpspec.h>
#include <asm/apic.h>
#include <asm/smp.h>
-#include <asm/genapic.h>
#include <asm/fixmap.h>
#include <asm/apicdef.h>
#include <asm/ipi.h>
@@ -209,16 +207,12 @@ static inline unsigned long summit_check_apicid_present(int bit)
return 1;
}
-#define apicid_cluster(apicid) ((apicid) & XAPIC_DEST_CLUSTER_MASK)
-
-extern u8 cpu_2_logical_apicid[];
-
static inline void summit_init_apic_ldr(void)
{
unsigned long val, id;
int count = 0;
u8 my_id = (u8)hard_smp_processor_id();
- u8 my_cluster = (u8)apicid_cluster(my_id);
+ u8 my_cluster = APIC_CLUSTER(my_id);
#ifdef CONFIG_SMP
u8 lid;
int i;
@@ -226,7 +220,7 @@ static inline void summit_init_apic_ldr(void)
/* Create logical APIC IDs by counting CPUs already in cluster. */
for (count = 0, i = nr_cpu_ids; --i >= 0; ) {
lid = cpu_2_logical_apicid[i];
- if (lid != BAD_APICID && apicid_cluster(lid) == my_cluster)
+ if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster)
++count;
}
#endif
@@ -266,7 +260,7 @@ static inline int summit_cpu_to_logical_apicid(int cpu)
#ifdef CONFIG_SMP
if (cpu >= nr_cpu_ids)
return BAD_APICID;
- return (int)cpu_2_logical_apicid[cpu];
+ return cpu_2_logical_apicid[cpu];
#else
return logical_smp_processor_id();
#endif
@@ -323,8 +317,7 @@ static inline unsigned int summit_cpu_mask_to_apicid(const cpumask_t *cpumask)
if (cpu_isset(cpu, *cpumask)) {
int new_apicid = summit_cpu_to_logical_apicid(cpu);
- if (apicid_cluster(apicid) !=
- apicid_cluster(new_apicid)) {
+ if (APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
printk ("%s: Not a valid mask!\n", __func__);
return 0xFF;
@@ -544,7 +537,7 @@ void __init setup_summit(void)
}
#endif
-struct genapic apic_summit = {
+struct apic apic_summit = {
.name = "summit",
.probe = probe_summit,
@@ -597,6 +590,12 @@ struct genapic apic_summit = {
.wait_for_init_deassert = default_wait_for_init_deassert,
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = default_inquire_remote_apic,
+
+ .read = native_apic_mem_read,
+ .write = native_apic_mem_write,
+ .icr_read = native_apic_icr_read,
+ .icr_write = native_apic_icr_write,
+ .wait_icr_idle = native_apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_apic_wait_icr_idle,
};
diff --git a/arch/x86/kernel/genx2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c
index 7c87156b6411..354b9c45601d 100644
--- a/arch/x86/kernel/genx2apic_cluster.c
+++ b/arch/x86/kernel/apic/x2apic_cluster.c
@@ -7,17 +7,14 @@
#include <linux/dmar.h>
#include <asm/smp.h>
+#include <asm/apic.h>
#include <asm/ipi.h>
-#include <asm/genapic.h>
DEFINE_PER_CPU(u32, x86_cpu_to_logical_apicid);
static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
- if (cpu_has_x2apic)
- return 1;
-
- return 0;
+ return x2apic_enabled();
}
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
@@ -46,7 +43,7 @@ static void
/*
* send the IPI.
*/
- x2apic_icr_write(cfg, apicid);
+ native_x2apic_icr_write(cfg, apicid);
}
/*
@@ -182,7 +179,7 @@ static void init_x2apic_ldr(void)
per_cpu(x86_cpu_to_logical_apicid, cpu) = apic_read(APIC_LDR);
}
-struct genapic apic_x2apic_cluster = {
+struct apic apic_x2apic_cluster = {
.name = "cluster x2apic",
.probe = NULL,
@@ -232,6 +229,12 @@ struct genapic apic_x2apic_cluster = {
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = NULL,
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = NULL,
+
+ .read = native_apic_msr_read,
+ .write = native_apic_msr_write,
+ .icr_read = native_x2apic_icr_read,
+ .icr_write = native_x2apic_icr_write,
+ .wait_icr_idle = native_x2apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle,
};
diff --git a/arch/x86/kernel/genx2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c
index 5cbae8aa0408..5bcb174409bc 100644
--- a/arch/x86/kernel/genx2apic_phys.c
+++ b/arch/x86/kernel/apic/x2apic_phys.c
@@ -7,10 +7,10 @@
#include <linux/dmar.h>
#include <asm/smp.h>
+#include <asm/apic.h>
#include <asm/ipi.h>
-#include <asm/genapic.h>
-static int x2apic_phys;
+int x2apic_phys;
static int set_x2apic_phys_mode(char *arg)
{
@@ -21,10 +21,10 @@ early_param("x2apic_phys", set_x2apic_phys_mode);
static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
- if (cpu_has_x2apic && x2apic_phys)
- return 1;
-
- return 0;
+ if (x2apic_phys)
+ return x2apic_enabled();
+ else
+ return 0;
}
/* Start with all IRQs pointing to boot CPU. IRQ balancing will shift them. */
@@ -50,7 +50,7 @@ static void __x2apic_send_IPI_dest(unsigned int apicid, int vector,
/*
* send the IPI.
*/
- x2apic_icr_write(cfg, apicid);
+ native_x2apic_icr_write(cfg, apicid);
}
static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
@@ -168,7 +168,7 @@ static void init_x2apic_ldr(void)
{
}
-struct genapic apic_x2apic_phys = {
+struct apic apic_x2apic_phys = {
.name = "physical x2apic",
.probe = NULL,
@@ -218,6 +218,12 @@ struct genapic apic_x2apic_phys = {
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = NULL,
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = NULL,
+
+ .read = native_apic_msr_read,
+ .write = native_apic_msr_write,
+ .icr_read = native_x2apic_icr_read,
+ .icr_write = native_x2apic_icr_write,
+ .wait_icr_idle = native_x2apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle,
};
diff --git a/arch/x86/kernel/genx2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c
index 89b84e004f04..20b4ad07c3a1 100644
--- a/arch/x86/kernel/genx2apic_uv_x.c
+++ b/arch/x86/kernel/apic/x2apic_uv_x.c
@@ -22,8 +22,8 @@
#include <linux/proc_fs.h>
#include <asm/current.h>
#include <asm/smp.h>
+#include <asm/apic.h>
#include <asm/ipi.h>
-#include <asm/genapic.h>
#include <asm/pgtable.h>
#include <asm/uv/uv.h>
#include <asm/uv/uv_mmrs.h>
@@ -240,7 +240,7 @@ static void uv_send_IPI_self(int vector)
apic_write(APIC_SELF_IPI, vector);
}
-struct genapic apic_x2apic_uv_x = {
+struct apic apic_x2apic_uv_x = {
.name = "UV large system",
.probe = NULL,
@@ -290,8 +290,14 @@ struct genapic apic_x2apic_uv_x = {
.trampoline_phys_high = DEFAULT_TRAMPOLINE_PHYS_HIGH,
.wait_for_init_deassert = NULL,
.smp_callin_clear_local_apic = NULL,
- .store_NMI_vector = NULL,
.inquire_remote_apic = NULL,
+
+ .read = native_apic_msr_read,
+ .write = native_apic_msr_write,
+ .icr_read = native_x2apic_icr_read,
+ .icr_write = native_x2apic_icr_write,
+ .wait_icr_idle = native_x2apic_wait_icr_idle,
+ .safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle,
};
static __cpuinit void set_x2apic_extra_bits(int pnode)
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 37ba5f85b718..10033fe718e0 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -1192,6 +1192,7 @@ static int suspend(int vetoable)
device_suspend(PMSG_SUSPEND);
local_irq_disable();
device_power_down(PMSG_SUSPEND);
+ sysdev_suspend(PMSG_SUSPEND);
local_irq_enable();
@@ -1208,6 +1209,7 @@ static int suspend(int vetoable)
if (err != APM_SUCCESS)
apm_error("suspend", err);
err = (err == APM_SUCCESS) ? 0 : -EIO;
+ sysdev_resume();
device_power_up(PMSG_RESUME);
local_irq_enable();
device_resume(PMSG_RESUME);
@@ -1228,6 +1230,7 @@ static void standby(void)
local_irq_disable();
device_power_down(PMSG_SUSPEND);
+ sysdev_suspend(PMSG_SUSPEND);
local_irq_enable();
err = set_system_power_state(APM_STATE_STANDBY);
@@ -1235,6 +1238,7 @@ static void standby(void)
apm_error("standby", err);
local_irq_disable();
+ sysdev_resume();
device_power_up(PMSG_RESUME);
local_irq_enable();
}
diff --git a/arch/x86/kernel/cpu/addon_cpuid_features.c b/arch/x86/kernel/cpu/addon_cpuid_features.c
index e48640cfac0c..6882a735d9c0 100644
--- a/arch/x86/kernel/cpu/addon_cpuid_features.c
+++ b/arch/x86/kernel/cpu/addon_cpuid_features.c
@@ -7,7 +7,7 @@
#include <asm/pat.h>
#include <asm/processor.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
struct cpuid_bit {
u16 feature;
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index ff4d7b9e32e4..25423a5b80ed 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -12,8 +12,6 @@
# include <asm/cacheflush.h>
#endif
-#include <asm/genapic.h>
-
#include "cpu.h"
#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4db150ed446d..826d5c876278 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -23,11 +23,9 @@
#include <asm/smp.h>
#include <asm/cpu.h>
#include <asm/cpumask.h>
-#ifdef CONFIG_X86_LOCAL_APIC
-#include <asm/mpspec.h>
#include <asm/apic.h>
-#include <asm/genapic.h>
-#include <asm/genapic.h>
+
+#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/uv/uv.h>
#endif
@@ -1051,7 +1049,7 @@ void __cpuinit cpu_init(void)
barrier();
check_efer();
- if (cpu != 0 && x2apic)
+ if (cpu != 0)
enable_x2apic();
/*
diff --git a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
index c2f930d86640..41ab3f064cb1 100644
--- a/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
+++ b/arch/x86/kernel/cpu/cpufreq/e_powersaver.c
@@ -204,12 +204,12 @@ static int eps_cpu_init(struct cpufreq_policy *policy)
}
/* Enable Enhanced PowerSaver */
rdmsrl(MSR_IA32_MISC_ENABLE, val);
- if (!(val & 1 << 16)) {
- val |= 1 << 16;
+ if (!(val & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
+ val |= MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP;
wrmsrl(MSR_IA32_MISC_ENABLE, val);
/* Can be locked at 0 */
rdmsrl(MSR_IA32_MISC_ENABLE, val);
- if (!(val & 1 << 16)) {
+ if (!(val & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
printk(KERN_INFO "eps: Can't enable Enhanced PowerSaver\n");
return -ENODEV;
}
diff --git a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
index fb039cd345d8..6428aa17b40e 100644
--- a/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
@@ -1157,8 +1157,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
data->cpu = pol->cpu;
data->currpstate = HW_PSTATE_INVALID;
- rc = powernow_k8_cpu_init_acpi(data);
- if (rc) {
+ if (powernow_k8_cpu_init_acpi(data)) {
/*
* Use the PSB BIOS structure. This is only availabe on
* an UP version, and is deprecated by AMD.
@@ -1176,17 +1175,20 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
"ACPI maintainers and complain to your BIOS "
"vendor.\n");
#endif
- goto err_out;
+ kfree(data);
+ return -ENODEV;
}
if (pol->cpu != 0) {
printk(KERN_ERR FW_BUG PFX "No ACPI _PSS objects for "
"CPU other than CPU0. Complain to your BIOS "
"vendor.\n");
- goto err_out;
+ kfree(data);
+ return -ENODEV;
}
rc = find_psb_table(data);
if (rc) {
- goto err_out;
+ kfree(data);
+ return -ENODEV;
}
/* Take a crude guess here.
* That guess was in microseconds, so multiply with 1000 */
diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
index f08998278a3a..c9f1fdc02830 100644
--- a/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
+++ b/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c
@@ -390,14 +390,14 @@ static int centrino_cpu_init(struct cpufreq_policy *policy)
enable it if not. */
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
- if (!(l & (1<<16))) {
- l |= (1<<16);
+ if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
+ l |= MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP;
dprintk("trying to enable Enhanced SpeedStep (%x)\n", l);
wrmsr(MSR_IA32_MISC_ENABLE, l, h);
/* check to see if it stuck */
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
- if (!(l & (1<<16))) {
+ if (!(l & MSR_IA32_MISC_ENABLE_ENHANCED_SPEEDSTEP)) {
printk(KERN_INFO PFX
"couldn't enable Enhanced SpeedStep\n");
return -ENODEV;
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 1f137a87d4bd..25c559ba8d54 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -24,7 +24,6 @@
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/mpspec.h>
#include <asm/apic.h>
-#include <asm/genapic.h>
#endif
static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)
@@ -147,10 +146,10 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c)
*/
if ((c->x86 == 15) && (c->x86_model == 1) && (c->x86_mask == 1)) {
rdmsr(MSR_IA32_MISC_ENABLE, lo, hi);
- if ((lo & (1<<9)) == 0) {
+ if ((lo & MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE) == 0) {
printk (KERN_INFO "CPU: C0 stepping P4 Xeon detected.\n");
printk (KERN_INFO "CPU: Disabling hardware prefetching (Errata 037)\n");
- lo |= (1<<9); /* Disable hw prefetching */
+ lo |= MSR_IA32_MISC_ENABLE_PREFETCH_DISABLE;
wrmsr (MSR_IA32_MISC_ENABLE, lo, hi);
}
}
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c
index 1c838032fd37..fe79985ce0f2 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_64.c
@@ -295,11 +295,11 @@ void do_machine_check(struct pt_regs * regs, long error_code)
* If we know that the error was in user space, send a
* SIGBUS. Otherwise, panic if tolerance is low.
*
- * do_exit() takes an awful lot of locks and has a slight
+ * force_sig() takes an awful lot of locks and has a slight
* risk of deadlocking.
*/
if (user_space) {
- do_exit(SIGBUS);
+ force_sig(SIGBUS, current);
} else if (panic_on_oops || tolerant < 2) {
mce_panic("Uncorrected machine check",
&panicm, mcestart);
@@ -490,7 +490,7 @@ static void __cpuinit mce_cpu_quirks(struct cpuinfo_x86 *c)
}
-static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c)
+static void mce_cpu_features(struct cpuinfo_x86 *c)
{
switch (c->x86_vendor) {
case X86_VENDOR_INTEL:
@@ -734,6 +734,7 @@ __setup("mce=", mcheck_enable);
static int mce_resume(struct sys_device *dev)
{
mce_init(NULL);
+ mce_cpu_features(&current_cpu_data);
return 0;
}
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
index 4772e91e8246..9817506dd469 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd_64.c
@@ -121,7 +121,7 @@ static long threshold_restart_bank(void *_tr)
}
/* cpu init entry point, called from mce.c with preempt off */
-void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
+void mce_amd_feature_init(struct cpuinfo_x86 *c)
{
unsigned int bank, block;
unsigned int cpu = smp_processor_id();
diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
index 5e8c79e748a6..aa5e287c98e0 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_intel_64.c
@@ -31,7 +31,7 @@ asmlinkage void smp_thermal_interrupt(void)
irq_exit();
}
-static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
+static void intel_init_thermal(struct cpuinfo_x86 *c)
{
u32 l, h;
int tm2 = 0;
@@ -49,13 +49,13 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
*/
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
h = apic_read(APIC_LVTTHMR);
- if ((l & (1 << 3)) && (h & APIC_DM_SMI)) {
+ if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
printk(KERN_DEBUG
"CPU%d: Thermal monitoring handled by SMI\n", cpu);
return;
}
- if (cpu_has(c, X86_FEATURE_TM2) && (l & (1 << 13)))
+ if (cpu_has(c, X86_FEATURE_TM2) && (l & MSR_IA32_MISC_ENABLE_TM2))
tm2 = 1;
if (h & APIC_VECTOR_MASK) {
@@ -73,7 +73,7 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
wrmsr(MSR_IA32_THERM_INTERRUPT, l | 0x03, h);
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
- wrmsr(MSR_IA32_MISC_ENABLE, l | (1 << 3), h);
+ wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
l = apic_read(APIC_LVTTHMR);
apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
@@ -85,7 +85,7 @@ static void __cpuinit intel_init_thermal(struct cpuinfo_x86 *c)
return;
}
-void __cpuinit mce_intel_feature_init(struct cpuinfo_x86 *c)
+void mce_intel_feature_init(struct cpuinfo_x86 *c)
{
intel_init_thermal(c);
}
diff --git a/arch/x86/kernel/cpu/mcheck/p4.c b/arch/x86/kernel/cpu/mcheck/p4.c
index 9b60fce09f75..f53bdcbaf382 100644
--- a/arch/x86/kernel/cpu/mcheck/p4.c
+++ b/arch/x86/kernel/cpu/mcheck/p4.c
@@ -85,7 +85,7 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
*/
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
h = apic_read(APIC_LVTTHMR);
- if ((l & (1<<3)) && (h & APIC_DM_SMI)) {
+ if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
printk(KERN_DEBUG "CPU%d: Thermal monitoring handled by SMI\n",
cpu);
return; /* -EBUSY */
@@ -111,7 +111,7 @@ static void intel_init_thermal(struct cpuinfo_x86 *c)
vendor_thermal_interrupt = intel_thermal_interrupt;
rdmsr(MSR_IA32_MISC_ENABLE, l, h);
- wrmsr(MSR_IA32_MISC_ENABLE, l | (1<<3), h);
+ wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
l = apic_read(APIC_LVTTHMR);
apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
diff --git a/arch/x86/kernel/cpu/perfctr-watchdog.c b/arch/x86/kernel/cpu/perfctr-watchdog.c
index 9abd48b22674..f6c70a164e32 100644
--- a/arch/x86/kernel/cpu/perfctr-watchdog.c
+++ b/arch/x86/kernel/cpu/perfctr-watchdog.c
@@ -19,7 +19,7 @@
#include <linux/nmi.h>
#include <linux/kprobes.h>
-#include <asm/apic.h>
+#include <asm/genapic.h>
#include <asm/intel_arch_perfmon.h>
struct nmi_watchdog_ctlblk {
diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c
index ad7f2a696f4a..ff958248e61d 100644
--- a/arch/x86/kernel/crash.c
+++ b/arch/x86/kernel/crash.c
@@ -28,8 +28,6 @@
#include <asm/reboot.h>
#include <asm/virtext.h>
-#include <asm/genapic.h>
-
#if defined(CONFIG_SMP) && defined(CONFIG_X86_LOCAL_APIC)
diff --git a/arch/x86/kernel/efi_stub_32.S b/arch/x86/kernel/efi_stub_32.S
index a206b9469296..fbe66e626c09 100644
--- a/arch/x86/kernel/efi_stub_32.S
+++ b/arch/x86/kernel/efi_stub_32.S
@@ -6,7 +6,7 @@
*/
#include <linux/linkage.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
/*
* efi_call_phys(void *, ...) is a function with variable parameters.
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index e99206831459..899e8938e79f 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -47,7 +47,7 @@
#include <asm/errno.h>
#include <asm/segment.h>
#include <asm/smp.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/desc.h>
#include <asm/percpu.h>
#include <asm/dwarf2.h>
@@ -1359,7 +1359,7 @@ nmi_espfix_stack:
CFI_ADJUST_CFA_OFFSET 4
pushl %esp
CFI_ADJUST_CFA_OFFSET 4
- addw $4, (%esp)
+ addl $4, (%esp)
/* copy the iret frame of 12 bytes */
.rept 3
pushl 16(%esp)
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 8a6c7c63885f..83d1836b9467 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -48,7 +48,7 @@
#include <asm/unistd.h>
#include <asm/thread_info.h>
#include <asm/hw_irq.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/irqflags.h>
#include <asm/paravirt.h>
#include <asm/ftrace.h>
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 2a0aad7718d5..c32ca19d591a 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -11,8 +11,8 @@
#include <linux/init.h>
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
+#include <asm/page_types.h>
+#include <asm/pgtable_types.h>
#include <asm/desc.h>
#include <asm/cache.h>
#include <asm/thread_info.h>
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 11d5093eb281..df89102bef80 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -22,7 +22,6 @@
#include <asm/pgtable.h>
#include <asm/desc.h>
#include <asm/apic.h>
-#include <asm/arch_hooks.h>
#include <asm/i8259.h>
/*
diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c
index 4beb9a13873d..9dc6b2b24275 100644
--- a/arch/x86/kernel/irq_32.c
+++ b/arch/x86/kernel/irq_32.c
@@ -212,7 +212,6 @@ bool handle_irq(unsigned irq, struct pt_regs *regs)
}
#ifdef CONFIG_HOTPLUG_CPU
-#include <asm/genapic.h>
/* A cpu has been removed from cpu_online_mask. Reset irq affinities. */
void fixup_irqs(void)
diff --git a/arch/x86/kernel/irqinit_32.c b/arch/x86/kernel/irqinit_32.c
index bf629cadec1a..50b8c3a3006c 100644
--- a/arch/x86/kernel/irqinit_32.c
+++ b/arch/x86/kernel/irqinit_32.c
@@ -18,7 +18,7 @@
#include <asm/pgtable.h>
#include <asm/desc.h>
#include <asm/apic.h>
-#include <asm/arch_hooks.h>
+#include <asm/setup.h>
#include <asm/i8259.h>
#include <asm/traps.h>
@@ -127,8 +127,8 @@ void __init native_init_IRQ(void)
{
int i;
- /* all the set up before the call gates are initialised */
- pre_intr_init_hook();
+ /* Execute any quirks before the call gates are initialised: */
+ x86_quirk_pre_intr_init();
/*
* Cover the whole vector space, no vector can escape
@@ -188,10 +188,11 @@ void __init native_init_IRQ(void)
if (!acpi_ioapic)
setup_irq(2, &irq2);
- /* setup after call gates are initialised (usually add in
- * the architecture specific gates)
+ /*
+ * Call quirks after call gates are initialised (usually add in
+ * the architecture specific gates):
*/
- intr_init_hook();
+ x86_quirk_intr_init();
/*
* External FPU? Set up irq13 if so, for
diff --git a/arch/x86/kernel/kgdb.c b/arch/x86/kernel/kgdb.c
index 5c4f55483849..eedfaebe1063 100644
--- a/arch/x86/kernel/kgdb.c
+++ b/arch/x86/kernel/kgdb.c
@@ -46,7 +46,7 @@
#include <asm/apicdef.h>
#include <asm/system.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
/*
* Put the error code here just in case the user cares:
diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c
index 652fce6d2cce..137f2e8132df 100644
--- a/arch/x86/kernel/kvmclock.c
+++ b/arch/x86/kernel/kvmclock.c
@@ -19,7 +19,6 @@
#include <linux/clocksource.h>
#include <linux/kvm_para.h>
#include <asm/pvclock.h>
-#include <asm/arch_hooks.h>
#include <asm/msr.h>
#include <asm/apic.h>
#include <linux/percpu.h>
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 37f420018a41..f5fc8c781a62 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -121,7 +121,7 @@ static void machine_kexec_page_table_set_one(
static void machine_kexec_prepare_page_tables(struct kimage *image)
{
void *control_page;
- pmd_t *pmd = 0;
+ pmd_t *pmd = NULL;
control_page = page_address(image->control_code_page);
#ifdef CONFIG_X86_PAE
diff --git a/arch/x86/kernel/mca_32.c b/arch/x86/kernel/mca_32.c
index 2dc183758be3..845d80ce1ef1 100644
--- a/arch/x86/kernel/mca_32.c
+++ b/arch/x86/kernel/mca_32.c
@@ -51,7 +51,6 @@
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <linux/init.h>
-#include <asm/arch_hooks.h>
static unsigned char which_scsi;
@@ -474,6 +473,4 @@ void __kprobes mca_handle_nmi(void)
* adapter was responsible for the error.
*/
bus_for_each_dev(&mca_bus_type, NULL, NULL, mca_handle_nmi_callback);
-
- mca_nmi_hook();
-} /* mca_handle_nmi */
+}
diff --git a/arch/x86/kernel/mpparse.c b/arch/x86/kernel/mpparse.c
index 200764453195..37cb1bda1baf 100644
--- a/arch/x86/kernel/mpparse.c
+++ b/arch/x86/kernel/mpparse.c
@@ -29,7 +29,7 @@
#include <asm/setup.h>
#include <asm/smp.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
/*
* Checksum an MP configuration block.
*/
@@ -710,13 +710,22 @@ static int __init smp_scan_config(unsigned long base, unsigned long length,
* of physical memory; so that simply reserving
* PAGE_SIZE from mpf->physptr yields BUG()
* in reserve_bootmem.
+ * also need to make sure physptr is below than
+ * max_low_pfn
+ * we don't need reserve the area above max_low_pfn
*/
unsigned long end = max_low_pfn * PAGE_SIZE;
- if (mpf->physptr + size > end)
- size = end - mpf->physptr;
-#endif
+
+ if (mpf->physptr < end) {
+ if (mpf->physptr + size > end)
+ size = end - mpf->physptr;
+ reserve_bootmem_generic(mpf->physptr, size,
+ BOOTMEM_DEFAULT);
+ }
+#else
reserve_bootmem_generic(mpf->physptr, size,
BOOTMEM_DEFAULT);
+#endif
}
return 1;
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 6dc4dca255e4..63dd358d8ee1 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -28,7 +28,6 @@
#include <asm/paravirt.h>
#include <asm/desc.h>
#include <asm/setup.h>
-#include <asm/arch_hooks.h>
#include <asm/pgtable.h>
#include <asm/time.h>
#include <asm/pgalloc.h>
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index fec79ad85dc6..646da41a620a 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -111,9 +111,6 @@ void cpu_idle(void)
check_pgt_cache();
rmb();
- if (rcu_pending(cpu))
- rcu_check_callbacks(cpu, 0);
-
if (cpu_is_offline(cpu))
play_dead();
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index d2f7cd5b2c83..fb2159a5c817 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -268,7 +268,7 @@ static unsigned long debugreg_addr_limit(struct task_struct *task)
if (test_tsk_thread_flag(task, TIF_IA32))
return IA32_PAGE_OFFSET - 3;
#endif
- return TASK_SIZE64 - 7;
+ return TASK_SIZE_MAX - 7;
}
#endif /* CONFIG_X86_32 */
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 32e8f0af292c..1cc18d439bbb 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -24,8 +24,6 @@
# include <asm/iommu.h>
#endif
-#include <asm/genapic.h>
-
/*
* Power off function, if any
*/
diff --git a/arch/x86/kernel/relocate_kernel_32.S b/arch/x86/kernel/relocate_kernel_32.S
index a160f3119725..2064d0aa8d28 100644
--- a/arch/x86/kernel/relocate_kernel_32.S
+++ b/arch/x86/kernel/relocate_kernel_32.S
@@ -7,7 +7,7 @@
*/
#include <linux/linkage.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/kexec.h>
#include <asm/processor-flags.h>
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index b0bbdd4829c9..d32cfb27a479 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -7,10 +7,10 @@
*/
#include <linux/linkage.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/kexec.h>
#include <asm/processor-flags.h>
-#include <asm/pgtable.h>
+#include <asm/pgtable_types.h>
/*
* Must be relocatable PIC code callable as a C function
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 8fce6c714514..5b85759e7972 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -74,8 +74,9 @@
#include <asm/e820.h>
#include <asm/mpspec.h>
#include <asm/setup.h>
-#include <asm/arch_hooks.h>
#include <asm/efi.h>
+#include <asm/timer.h>
+#include <asm/i8259.h>
#include <asm/sections.h>
#include <asm/dmi.h>
#include <asm/io_apic.h>
@@ -97,7 +98,6 @@
#include <asm/mmu_context.h>
#include <asm/proto.h>
-#include <asm/genapic.h>
#include <asm/paravirt.h>
#include <asm/hypervisor.h>
@@ -600,7 +600,7 @@ static int __init setup_elfcorehdr(char *arg)
early_param("elfcorehdr", setup_elfcorehdr);
#endif
-static int __init default_update_genapic(void)
+static int __init default_update_apic(void)
{
#ifdef CONFIG_SMP
if (!apic->wakeup_cpu)
@@ -611,7 +611,7 @@ static int __init default_update_genapic(void)
}
static struct x86_quirks default_x86_quirks __initdata = {
- .update_genapic = default_update_genapic,
+ .update_apic = default_update_apic,
};
struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
@@ -669,7 +669,6 @@ void __init setup_arch(char **cmdline_p)
#ifdef CONFIG_X86_32
memcpy(&boot_cpu_data, &new_cpu_data, sizeof(new_cpu_data));
visws_early_detect();
- pre_setup_arch_hook();
#else
printk(KERN_INFO "Command line: %s\n", boot_command_line);
#endif
@@ -836,8 +835,7 @@ void __init setup_arch(char **cmdline_p)
#else
num_physpages = max_pfn;
- if (cpu_has_x2apic)
- check_x2apic();
+ check_x2apic();
/* How many end-of-memory variables you have, grandma! */
/* need this before calling reserve_initrd */
@@ -987,4 +985,95 @@ void __init setup_arch(char **cmdline_p)
#endif
}
+#ifdef CONFIG_X86_32
+
+/**
+ * x86_quirk_pre_intr_init - initialisation prior to setting up interrupt vectors
+ *
+ * Description:
+ * Perform any necessary interrupt initialisation prior to setting up
+ * the "ordinary" interrupt call gates. For legacy reasons, the ISA
+ * interrupts should be initialised here if the machine emulates a PC
+ * in any way.
+ **/
+void __init x86_quirk_pre_intr_init(void)
+{
+ if (x86_quirks->arch_pre_intr_init) {
+ if (x86_quirks->arch_pre_intr_init())
+ return;
+ }
+ init_ISA_irqs();
+}
+
+/**
+ * x86_quirk_intr_init - post gate setup interrupt initialisation
+ *
+ * Description:
+ * Fill in any interrupts that may have been left out by the general
+ * init_IRQ() routine. interrupts having to do with the machine rather
+ * than the devices on the I/O bus (like APIC interrupts in intel MP
+ * systems) are started here.
+ **/
+void __init x86_quirk_intr_init(void)
+{
+ if (x86_quirks->arch_intr_init) {
+ if (x86_quirks->arch_intr_init())
+ return;
+ }
+}
+
+/**
+ * x86_quirk_trap_init - initialise system specific traps
+ *
+ * Description:
+ * Called as the final act of trap_init(). Used in VISWS to initialise
+ * the various board specific APIC traps.
+ **/
+void __init x86_quirk_trap_init(void)
+{
+ if (x86_quirks->arch_trap_init) {
+ if (x86_quirks->arch_trap_init())
+ return;
+ }
+}
+
+static struct irqaction irq0 = {
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
+ .mask = CPU_MASK_NONE,
+ .name = "timer"
+};
+
+/**
+ * x86_quirk_pre_time_init - do any specific initialisations before.
+ *
+ **/
+void __init x86_quirk_pre_time_init(void)
+{
+ if (x86_quirks->arch_pre_time_init)
+ x86_quirks->arch_pre_time_init();
+}
+/**
+ * x86_quirk_time_init - do any specific initialisations for the system timer.
+ *
+ * Description:
+ * Must plug the system timer interrupt source at HZ into the IRQ listed
+ * in irq_vectors.h:TIMER_IRQ
+ **/
+void __init x86_quirk_time_init(void)
+{
+ if (x86_quirks->arch_time_init) {
+ /*
+ * A nonzero return code does not mean failure, it means
+ * that the architecture quirk does not want any
+ * generic (timer) setup to be performed after this:
+ */
+ if (x86_quirks->arch_time_init())
+ return;
+ }
+
+ irq0.mask = cpumask_of_cpu(0);
+ setup_irq(0, &irq0);
+}
+#endif /* CONFIG_X86_32 */
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c
index eaaffae31cc0..13f33ea8ccaa 100644
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -26,7 +26,7 @@
#include <asm/tlbflush.h>
#include <asm/mmu_context.h>
#include <asm/proto.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
/*
* Some notes on x86 processor bugs affecting SMP operation:
*
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 10834954e301..9ce666387f37 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -60,12 +60,11 @@
#include <asm/tlbflush.h>
#include <asm/mtrr.h>
#include <asm/vmi.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
#include <asm/setup.h>
#include <asm/uv/uv.h>
#include <linux/mc146818rtc.h>
-#include <asm/genapic.h>
#include <asm/smpboot_hooks.h>
#ifdef CONFIG_X86_32
@@ -746,21 +745,21 @@ static void __cpuinit do_fork_idle(struct work_struct *work)
complete(&c_idle->done);
}
-static int __cpuinit do_boot_cpu(int apicid, int cpu)
/*
* NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad
* (ie clustered apic addressing mode), this is a LOGICAL apic ID.
* Returns zero if CPU booted OK, else error code from ->wakeup_cpu.
*/
+static int __cpuinit do_boot_cpu(int apicid, int cpu)
{
unsigned long boot_error = 0;
- int timeout;
unsigned long start_ip;
- unsigned short nmi_high = 0, nmi_low = 0;
+ int timeout;
struct create_idle c_idle = {
- .cpu = cpu,
- .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+ .cpu = cpu,
+ .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
};
+
INIT_WORK(&c_idle.work, do_fork_idle);
alternatives_smp_switch(1);
@@ -825,9 +824,6 @@ do_rest:
pr_debug("Setting warm reset code and vector.\n");
- if (apic->store_NMI_vector)
- apic->store_NMI_vector(&nmi_high, &nmi_low);
-
smpboot_setup_warm_reset_vector(start_ip);
/*
* Be paranoid about clearing APIC errors.
@@ -1128,8 +1124,8 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
current_thread_info()->cpu = 0; /* needed? */
set_cpu_sibling_map(0);
-#ifdef CONFIG_X86_64
enable_IR_x2apic();
+#ifdef CONFIG_X86_64
default_setup_apic_routing();
#endif
diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c
index 764c74e871f2..5c5d87f0b2e1 100644
--- a/arch/x86/kernel/time_32.c
+++ b/arch/x86/kernel/time_32.c
@@ -33,7 +33,7 @@
#include <linux/time.h>
#include <linux/mca.h>
-#include <asm/arch_hooks.h>
+#include <asm/setup.h>
#include <asm/hpet.h>
#include <asm/time.h>
#include <asm/timer.h>
@@ -118,7 +118,7 @@ void __init hpet_time_init(void)
{
if (!hpet_enable())
setup_pit_timer();
- time_init_hook();
+ x86_quirk_time_init();
}
/*
@@ -131,7 +131,7 @@ void __init hpet_time_init(void)
*/
void __init time_init(void)
{
- pre_time_init_hook();
+ x86_quirk_pre_time_init();
tsc_init();
late_time_init = choose_time_init();
}
diff --git a/arch/x86/kernel/time_64.c b/arch/x86/kernel/time_64.c
index e6e695acd725..241ec3923f61 100644
--- a/arch/x86/kernel/time_64.c
+++ b/arch/x86/kernel/time_64.c
@@ -115,7 +115,7 @@ unsigned long __init calibrate_cpu(void)
static struct irqaction irq0 = {
.handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING,
+ .flags = IRQF_DISABLED | IRQF_IRQPOLL | IRQF_NOBALANCING | IRQF_TIMER,
.mask = CPU_MASK_NONE,
.name = "timer"
};
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c
index f396e61bcb34..f04549afcfe9 100644
--- a/arch/x86/kernel/tlb_uv.c
+++ b/arch/x86/kernel/tlb_uv.c
@@ -15,13 +15,11 @@
#include <asm/uv/uv_mmrs.h>
#include <asm/uv/uv_hub.h>
#include <asm/uv/uv_bau.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
#include <asm/idle.h>
#include <asm/tsc.h>
#include <asm/irq_vectors.h>
-#include <asm/genapic.h>
-
static struct bau_control **uv_bau_table_bases __read_mostly;
static int uv_bau_retry_limit __read_mostly;
diff --git a/arch/x86/kernel/trampoline_32.S b/arch/x86/kernel/trampoline_32.S
index d8ccc3c6552f..66d874e5404c 100644
--- a/arch/x86/kernel/trampoline_32.S
+++ b/arch/x86/kernel/trampoline_32.S
@@ -29,7 +29,7 @@
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
/* We can free up trampoline after bootup if cpu hotplug is not supported. */
#ifndef CONFIG_HOTPLUG_CPU
diff --git a/arch/x86/kernel/trampoline_64.S b/arch/x86/kernel/trampoline_64.S
index 95a012a4664e..cddfb8d386b9 100644
--- a/arch/x86/kernel/trampoline_64.S
+++ b/arch/x86/kernel/trampoline_64.S
@@ -25,8 +25,8 @@
*/
#include <linux/linkage.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
+#include <asm/pgtable_types.h>
+#include <asm/page_types.h>
#include <asm/msr.h>
#include <asm/segment.h>
#include <asm/processor-flags.h>
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index acb8c0585ab9..c05430ac1b44 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -61,7 +61,7 @@
#include <asm/proto.h>
#else
#include <asm/processor-flags.h>
-#include <asm/arch_hooks.h>
+#include <asm/setup.h>
#include <asm/traps.h>
#include "cpu/mcheck/mce.h"
@@ -942,7 +942,7 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
info.si_signo = SIGILL;
info.si_errno = 0;
info.si_code = ILL_BADSTK;
- info.si_addr = 0;
+ info.si_addr = NULL;
if (notify_die(DIE_TRAP, "iret exception",
regs, error_code, 32, SIGILL) == NOTIFY_STOP)
return;
@@ -1026,6 +1026,6 @@ void __init trap_init(void)
cpu_init();
#ifdef CONFIG_X86_32
- trap_init_hook();
+ x86_quirk_trap_init();
#endif
}
diff --git a/arch/x86/kernel/visws_quirks.c b/arch/x86/kernel/visws_quirks.c
index 4fd646e6dd43..191a876e9e87 100644
--- a/arch/x86/kernel/visws_quirks.c
+++ b/arch/x86/kernel/visws_quirks.c
@@ -24,18 +24,14 @@
#include <asm/visws/cobalt.h>
#include <asm/visws/piix4.h>
-#include <asm/arch_hooks.h>
#include <asm/io_apic.h>
#include <asm/fixmap.h>
#include <asm/reboot.h>
#include <asm/setup.h>
+#include <asm/apic.h>
#include <asm/e820.h>
#include <asm/io.h>
-#include <asm/genapic.h>
-
-#include <asm/genapic.h>
-
#include <linux/kernel_stat.h>
#include <asm/i8259.h>
@@ -49,8 +45,6 @@
extern int no_broadcast;
-#include <asm/apic.h>
-
char visws_board_type = -1;
char visws_board_rev = -1;
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c
index f052c84ecbe4..2cc4a90e2cb3 100644
--- a/arch/x86/kernel/vmi_32.c
+++ b/arch/x86/kernel/vmi_32.c
@@ -798,8 +798,8 @@ static inline int __init activate_vmi(void)
#endif
#ifdef CONFIG_X86_LOCAL_APIC
- para_fill(apic_ops->read, APICRead);
- para_fill(apic_ops->write, APICWrite);
+ para_fill(apic->read, APICRead);
+ para_fill(apic->write, APICWrite);
#endif
/*
diff --git a/arch/x86/kernel/vmiclock_32.c b/arch/x86/kernel/vmiclock_32.c
index a4791ef412d1..33a788d5879c 100644
--- a/arch/x86/kernel/vmiclock_32.c
+++ b/arch/x86/kernel/vmiclock_32.c
@@ -28,7 +28,6 @@
#include <asm/vmi.h>
#include <asm/vmi_time.h>
-#include <asm/arch_hooks.h>
#include <asm/apicdef.h>
#include <asm/apic.h>
#include <asm/timer.h>
@@ -202,7 +201,7 @@ static irqreturn_t vmi_timer_interrupt(int irq, void *dev_id)
static struct irqaction vmi_clock_action = {
.name = "vmi-timer",
.handler = vmi_timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_NOBALANCING,
+ .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_TIMER,
.mask = CPU_MASK_ALL,
};
@@ -283,10 +282,12 @@ void __devinit vmi_time_ap_init(void)
#endif
/** vmi clocksource */
+static struct clocksource clocksource_vmi;
static cycle_t read_real_cycles(void)
{
- return vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
+ cycle_t ret = (cycle_t)vmi_timer_ops.get_cycle_counter(VMI_CYCLES_REAL);
+ return max(ret, clocksource_vmi.cycle_last);
}
static struct clocksource clocksource_vmi = {
diff --git a/arch/x86/kernel/vmlinux_32.lds.S b/arch/x86/kernel/vmlinux_32.lds.S
index 3eba7f7bac05..0d860963f268 100644
--- a/arch/x86/kernel/vmlinux_32.lds.S
+++ b/arch/x86/kernel/vmlinux_32.lds.S
@@ -12,7 +12,7 @@
#include <asm-generic/vmlinux.lds.h>
#include <asm/thread_info.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/cache.h>
#include <asm/boot.h>
diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S
index 087a7f2c639b..fbfced6f6800 100644
--- a/arch/x86/kernel/vmlinux_64.lds.S
+++ b/arch/x86/kernel/vmlinux_64.lds.S
@@ -6,7 +6,7 @@
#include <asm-generic/vmlinux.lds.h>
#include <asm/asm-offsets.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#undef i386 /* in case the preprocessor is a 32bit one */
diff --git a/arch/x86/kvm/i8254.c b/arch/x86/kvm/i8254.c
index e665d1c623ca..72bd275a9b5c 100644
--- a/arch/x86/kvm/i8254.c
+++ b/arch/x86/kvm/i8254.c
@@ -207,7 +207,7 @@ static int __pit_timer_fn(struct kvm_kpit_state *ps)
hrtimer_add_expires_ns(&pt->timer, pt->period);
pt->scheduled = hrtimer_get_expires_ns(&pt->timer);
if (pt->period)
- ps->channels[0].count_load_time = hrtimer_get_expires(&pt->timer);
+ ps->channels[0].count_load_time = ktime_get();
return (pt->period == 0 ? 0 : 1);
}
diff --git a/arch/x86/kvm/irq.c b/arch/x86/kvm/irq.c
index c019b8edcdb7..cf17ed52f6fb 100644
--- a/arch/x86/kvm/irq.c
+++ b/arch/x86/kvm/irq.c
@@ -87,13 +87,6 @@ void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu)
}
EXPORT_SYMBOL_GPL(kvm_inject_pending_timer_irqs);
-void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
-{
- kvm_apic_timer_intr_post(vcpu, vec);
- /* TODO: PIT, RTC etc. */
-}
-EXPORT_SYMBOL_GPL(kvm_timer_intr_post);
-
void __kvm_migrate_timers(struct kvm_vcpu *vcpu)
{
__kvm_migrate_apic_timer(vcpu);
diff --git a/arch/x86/kvm/irq.h b/arch/x86/kvm/irq.h
index 2bf32a03ceec..82579ee538d0 100644
--- a/arch/x86/kvm/irq.h
+++ b/arch/x86/kvm/irq.h
@@ -89,7 +89,6 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
void kvm_pic_reset(struct kvm_kpic_state *s);
-void kvm_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
void kvm_inject_pending_timer_irqs(struct kvm_vcpu *vcpu);
void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu);
void kvm_apic_nmi_wd_deliver(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index afac68c0815c..f0b67f2cdd69 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -35,6 +35,12 @@
#include "kvm_cache_regs.h"
#include "irq.h"
+#ifndef CONFIG_X86_64
+#define mod_64(x, y) ((x) - (y) * div64_u64(x, y))
+#else
+#define mod_64(x, y) ((x) % (y))
+#endif
+
#define PRId64 "d"
#define PRIx64 "llx"
#define PRIu64 "u"
@@ -511,52 +517,22 @@ static void apic_send_ipi(struct kvm_lapic *apic)
static u32 apic_get_tmcct(struct kvm_lapic *apic)
{
- u64 counter_passed;
- ktime_t passed, now;
+ ktime_t remaining;
+ s64 ns;
u32 tmcct;
ASSERT(apic != NULL);
- now = apic->timer.dev.base->get_time();
- tmcct = apic_get_reg(apic, APIC_TMICT);
-
/* if initial count is 0, current count should also be 0 */
- if (tmcct == 0)
+ if (apic_get_reg(apic, APIC_TMICT) == 0)
return 0;
- if (unlikely(ktime_to_ns(now) <=
- ktime_to_ns(apic->timer.last_update))) {
- /* Wrap around */
- passed = ktime_add(( {
- (ktime_t) {
- .tv64 = KTIME_MAX -
- (apic->timer.last_update).tv64}; }
- ), now);
- apic_debug("time elapsed\n");
- } else
- passed = ktime_sub(now, apic->timer.last_update);
-
- counter_passed = div64_u64(ktime_to_ns(passed),
- (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
-
- if (counter_passed > tmcct) {
- if (unlikely(!apic_lvtt_period(apic))) {
- /* one-shot timers stick at 0 until reset */
- tmcct = 0;
- } else {
- /*
- * periodic timers reset to APIC_TMICT when they
- * hit 0. The while loop simulates this happening N
- * times. (counter_passed %= tmcct) would also work,
- * but might be slower or not work on 32-bit??
- */
- while (counter_passed > tmcct)
- counter_passed -= tmcct;
- tmcct -= counter_passed;
- }
- } else {
- tmcct -= counter_passed;
- }
+ remaining = hrtimer_expires_remaining(&apic->timer.dev);
+ if (ktime_to_ns(remaining) < 0)
+ remaining = ktime_set(0, 0);
+
+ ns = mod_64(ktime_to_ns(remaining), apic->timer.period);
+ tmcct = div64_u64(ns, (APIC_BUS_CYCLE_NS * apic->timer.divide_count));
return tmcct;
}
@@ -653,8 +629,6 @@ static void start_apic_timer(struct kvm_lapic *apic)
{
ktime_t now = apic->timer.dev.base->get_time();
- apic->timer.last_update = now;
-
apic->timer.period = apic_get_reg(apic, APIC_TMICT) *
APIC_BUS_CYCLE_NS * apic->timer.divide_count;
atomic_set(&apic->timer.pending, 0);
@@ -1110,16 +1084,6 @@ void kvm_inject_apic_timer_irqs(struct kvm_vcpu *vcpu)
}
}
-void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec)
-{
- struct kvm_lapic *apic = vcpu->arch.apic;
-
- if (apic && apic_lvt_vector(apic, APIC_LVTT) == vec)
- apic->timer.last_update = ktime_add_ns(
- apic->timer.last_update,
- apic->timer.period);
-}
-
int kvm_get_apic_interrupt(struct kvm_vcpu *vcpu)
{
int vector = kvm_apic_has_interrupt(vcpu);
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 81858881287e..45ab6ee71209 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -12,7 +12,6 @@ struct kvm_lapic {
atomic_t pending;
s64 period; /* unit: ns */
u32 divide_count;
- ktime_t last_update;
struct hrtimer dev;
} timer;
struct kvm_vcpu *vcpu;
@@ -42,7 +41,6 @@ void kvm_set_apic_base(struct kvm_vcpu *vcpu, u64 data);
void kvm_apic_post_state_restore(struct kvm_vcpu *vcpu);
int kvm_lapic_enabled(struct kvm_vcpu *vcpu);
int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
-void kvm_apic_timer_intr_post(struct kvm_vcpu *vcpu, int vec);
void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr);
void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 83f11c7474a1..2d4477c71473 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1698,8 +1698,13 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *shadow_pte,
if (largepage)
spte |= PT_PAGE_SIZE_MASK;
if (mt_mask) {
- mt_mask = get_memory_type(vcpu, gfn) <<
- kvm_x86_ops->get_mt_mask_shift();
+ if (!kvm_is_mmio_pfn(pfn)) {
+ mt_mask = get_memory_type(vcpu, gfn) <<
+ kvm_x86_ops->get_mt_mask_shift();
+ mt_mask |= VMX_EPT_IGMT_BIT;
+ } else
+ mt_mask = MTRR_TYPE_UNCACHABLE <<
+ kvm_x86_ops->get_mt_mask_shift();
spte |= mt_mask;
}
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 1452851ae258..a9e769e4e251 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1600,7 +1600,6 @@ static void svm_intr_assist(struct kvm_vcpu *vcpu)
/* Okay, we can deliver the interrupt: grab it and update PIC state. */
intr_vector = kvm_cpu_get_interrupt(vcpu);
svm_inject_irq(svm, intr_vector);
- kvm_timer_intr_post(vcpu, intr_vector);
out:
update_cr8_intercept(vcpu);
}
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 6259d7467648..7611af576829 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -903,6 +903,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *pdata)
data = vmcs_readl(GUEST_SYSENTER_ESP);
break;
default:
+ vmx_load_host_state(to_vmx(vcpu));
msr = find_msr_entry(to_vmx(vcpu), msr_index);
if (msr) {
data = msr->data;
@@ -3285,7 +3286,6 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu)
}
if (vcpu->arch.interrupt.pending) {
vmx_inject_irq(vcpu, vcpu->arch.interrupt.nr);
- kvm_timer_intr_post(vcpu, vcpu->arch.interrupt.nr);
if (kvm_cpu_has_interrupt(vcpu))
enable_irq_window(vcpu);
}
@@ -3687,8 +3687,7 @@ static int __init vmx_init(void)
if (vm_need_ept()) {
bypass_guest_pf = 0;
kvm_mmu_set_base_ptes(VMX_EPT_READABLE_MASK |
- VMX_EPT_WRITABLE_MASK |
- VMX_EPT_IGMT_BIT);
+ VMX_EPT_WRITABLE_MASK);
kvm_mmu_set_mask_ptes(0ull, 0ull, 0ull, 0ull,
VMX_EPT_EXECUTABLE_MASK,
VMX_EPT_DEFAULT_MT << VMX_EPT_MT_EPTE_SHIFT);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index cc17546a2406..758b7a155ae9 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -967,7 +967,6 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_MMU_SHADOW_CACHE_CONTROL:
case KVM_CAP_SET_TSS_ADDR:
case KVM_CAP_EXT_CPUID:
- case KVM_CAP_CLOCKSOURCE:
case KVM_CAP_PIT:
case KVM_CAP_NOP_IO_DELAY:
case KVM_CAP_MP_STATE:
@@ -992,6 +991,9 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_IOMMU:
r = iommu_found();
break;
+ case KVM_CAP_CLOCKSOURCE:
+ r = boot_cpu_has(X86_FEATURE_CONSTANT_TSC);
+ break;
default:
r = 0;
break;
@@ -4127,9 +4129,13 @@ static void kvm_free_vcpus(struct kvm *kvm)
}
-void kvm_arch_destroy_vm(struct kvm *kvm)
+void kvm_arch_sync_events(struct kvm *kvm)
{
kvm_free_all_assigned_devices(kvm);
+}
+
+void kvm_arch_destroy_vm(struct kvm *kvm)
+{
kvm_iommu_unmap_guest(kvm);
kvm_free_pit(kvm);
kfree(kvm->arch.vpic);
diff --git a/arch/x86/lguest/Kconfig b/arch/x86/lguest/Kconfig
index c70e12b1a637..8dab8f7844d3 100644
--- a/arch/x86/lguest/Kconfig
+++ b/arch/x86/lguest/Kconfig
@@ -3,7 +3,6 @@ config LGUEST_GUEST
select PARAVIRT
depends on X86_32
depends on !X86_PAE
- depends on !X86_VOYAGER
select VIRTIO
select VIRTIO_RING
select VIRTIO_CONSOLE
diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
index da2e314f61b5..f3a5305b8adf 100644
--- a/arch/x86/lguest/boot.c
+++ b/arch/x86/lguest/boot.c
@@ -828,13 +828,14 @@ static u32 lguest_apic_safe_wait_icr_idle(void)
return 0;
}
-static struct apic_ops lguest_basic_apic_ops = {
- .read = lguest_apic_read,
- .write = lguest_apic_write,
- .icr_read = lguest_apic_icr_read,
- .icr_write = lguest_apic_icr_write,
- .wait_icr_idle = lguest_apic_wait_icr_idle,
- .safe_wait_icr_idle = lguest_apic_safe_wait_icr_idle,
+static void set_lguest_basic_apic_ops(void)
+{
+ apic->read = lguest_apic_read;
+ apic->write = lguest_apic_write;
+ apic->icr_read = lguest_apic_icr_read;
+ apic->icr_write = lguest_apic_icr_write;
+ apic->wait_icr_idle = lguest_apic_wait_icr_idle;
+ apic->safe_wait_icr_idle = lguest_apic_safe_wait_icr_idle;
};
#endif
@@ -1035,7 +1036,7 @@ __init void lguest_init(void)
#ifdef CONFIG_X86_LOCAL_APIC
/* apic read/write intercepts */
- apic_ops = &lguest_basic_apic_ops;
+ set_lguest_basic_apic_ops();
#endif
/* time operations */
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index ad374003742f..51f1504cddd9 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -28,7 +28,7 @@
#include <linux/linkage.h>
#include <asm/dwarf2.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/errno.h>
#include <asm/asm-offsets.h>
#include <asm/thread_info.h>
diff --git a/arch/x86/mach-voyager/Makefile b/arch/x86/mach-voyager/Makefile
deleted file mode 100644
index 15c250b371d3..000000000000
--- a/arch/x86/mach-voyager/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-EXTRA_CFLAGS := -Iarch/x86/kernel
-obj-y := setup.o voyager_basic.o voyager_thread.o
-
-obj-$(CONFIG_SMP) += voyager_smp.o voyager_cat.o
diff --git a/arch/x86/mach-voyager/setup.c b/arch/x86/mach-voyager/setup.c
deleted file mode 100644
index 66b7eb57d8e4..000000000000
--- a/arch/x86/mach-voyager/setup.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Machine specific setup for generic
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <asm/arch_hooks.h>
-#include <asm/voyager.h>
-#include <asm/e820.h>
-#include <asm/io.h>
-#include <asm/setup.h>
-#include <asm/cpu.h>
-
-void __init pre_intr_init_hook(void)
-{
- init_ISA_irqs();
-}
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2 = {
- .handler = no_action,
- .mask = CPU_MASK_NONE,
- .name = "cascade",
-};
-
-void __init intr_init_hook(void)
-{
-#ifdef CONFIG_SMP
- voyager_smp_intr_init();
-#endif
-
- setup_irq(2, &irq2);
-}
-
-static void voyager_disable_tsc(void)
-{
- /* Voyagers run their CPUs from independent clocks, so disable
- * the TSC code because we can't sync them */
- setup_clear_cpu_cap(X86_FEATURE_TSC);
-}
-
-void __init pre_setup_arch_hook(void)
-{
- voyager_disable_tsc();
-}
-
-void __init pre_time_init_hook(void)
-{
- voyager_disable_tsc();
-}
-
-void __init trap_init_hook(void)
-{
-}
-
-static struct irqaction irq0 = {
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
- .mask = CPU_MASK_NONE,
- .name = "timer"
-};
-
-void __init time_init_hook(void)
-{
- irq0.mask = cpumask_of_cpu(safe_smp_processor_id());
- setup_irq(0, &irq0);
-}
-
-/* Hook for machine specific memory setup. */
-
-char *__init machine_specific_memory_setup(void)
-{
- char *who;
- int new_nr;
-
- who = "NOT VOYAGER";
-
- if (voyager_level == 5) {
- __u32 addr, length;
- int i;
-
- who = "Voyager-SUS";
-
- e820.nr_map = 0;
- for (i = 0; voyager_memory_detect(i, &addr, &length); i++) {
- e820_add_region(addr, length, E820_RAM);
- }
- return who;
- } else if (voyager_level == 4) {
- __u32 tom;
- __u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT) << 8;
- /* select the DINO config space */
- outb(VOYAGER_DINO, VOYAGER_CAT_CONFIG_PORT);
- /* Read DINO top of memory register */
- tom = ((inb(catbase + 0x4) & 0xf0) << 16)
- + ((inb(catbase + 0x5) & 0x7f) << 24);
-
- if (inb(catbase) != VOYAGER_DINO) {
- printk(KERN_ERR
- "Voyager: Failed to get DINO for L4, setting tom to EXT_MEM_K\n");
- tom = (boot_params.screen_info.ext_mem_k) << 10;
- }
- who = "Voyager-TOM";
- e820_add_region(0, 0x9f000, E820_RAM);
- /* map from 1M to top of memory */
- e820_add_region(1 * 1024 * 1024, tom - 1 * 1024 * 1024,
- E820_RAM);
- /* FIXME: Should check the ASICs to see if I need to
- * take out the 8M window. Just do it at the moment
- * */
- e820_add_region(8 * 1024 * 1024, 8 * 1024 * 1024,
- E820_RESERVED);
- return who;
- }
-
- return default_machine_specific_memory_setup();
-}
diff --git a/arch/x86/mach-voyager/voyager_basic.c b/arch/x86/mach-voyager/voyager_basic.c
deleted file mode 100644
index 46d6f8067690..000000000000
--- a/arch/x86/mach-voyager/voyager_basic.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/* Copyright (C) 1999,2001
- *
- * Author: J.E.J.Bottomley@HansenPartnership.com
- *
- * This file contains all the voyager specific routines for getting
- * initialisation of the architecture to function. For additional
- * features see:
- *
- * voyager_cat.c - Voyager CAT bus interface
- * voyager_smp.c - Voyager SMP hal (emulates linux smp.c)
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/reboot.h>
-#include <linux/sysrq.h>
-#include <linux/smp.h>
-#include <linux/nodemask.h>
-#include <asm/io.h>
-#include <asm/voyager.h>
-#include <asm/vic.h>
-#include <linux/pm.h>
-#include <asm/tlbflush.h>
-#include <asm/arch_hooks.h>
-#include <asm/i8253.h>
-
-/*
- * Power off function, if any
- */
-void (*pm_power_off) (void);
-EXPORT_SYMBOL(pm_power_off);
-
-int voyager_level = 0;
-
-struct voyager_SUS *voyager_SUS = NULL;
-
-#ifdef CONFIG_SMP
-static void voyager_dump(int dummy1, struct tty_struct *dummy3)
-{
- /* get here via a sysrq */
- voyager_smp_dump();
-}
-
-static struct sysrq_key_op sysrq_voyager_dump_op = {
- .handler = voyager_dump,
- .help_msg = "Voyager",
- .action_msg = "Dump Voyager Status",
-};
-#endif
-
-void voyager_detect(struct voyager_bios_info *bios)
-{
- if (bios->len != 0xff) {
- int class = (bios->class_1 << 8)
- | (bios->class_2 & 0xff);
-
- printk("Voyager System detected.\n"
- " Class %x, Revision %d.%d\n",
- class, bios->major, bios->minor);
- if (class == VOYAGER_LEVEL4)
- voyager_level = 4;
- else if (class < VOYAGER_LEVEL5_AND_ABOVE)
- voyager_level = 3;
- else
- voyager_level = 5;
- printk(" Architecture Level %d\n", voyager_level);
- if (voyager_level < 4)
- printk
- ("\n**WARNING**: Voyager HAL only supports Levels 4 and 5 Architectures at the moment\n\n");
- /* install the power off handler */
- pm_power_off = voyager_power_off;
-#ifdef CONFIG_SMP
- register_sysrq_key('v', &sysrq_voyager_dump_op);
-#endif
- } else {
- printk("\n\n**WARNING**: No Voyager Subsystem Found\n");
- }
-}
-
-void voyager_system_interrupt(int cpl, void *dev_id)
-{
- printk("Voyager: detected system interrupt\n");
-}
-
-/* Routine to read information from the extended CMOS area */
-__u8 voyager_extended_cmos_read(__u16 addr)
-{
- outb(addr & 0xff, 0x74);
- outb((addr >> 8) & 0xff, 0x75);
- return inb(0x76);
-}
-
-/* internal definitions for the SUS Click Map of memory */
-
-#define CLICK_ENTRIES 16
-#define CLICK_SIZE 4096 /* click to byte conversion for Length */
-
-typedef struct ClickMap {
- struct Entry {
- __u32 Address;
- __u32 Length;
- } Entry[CLICK_ENTRIES];
-} ClickMap_t;
-
-/* This routine is pretty much an awful hack to read the bios clickmap by
- * mapping it into page 0. There are usually three regions in the map:
- * Base Memory
- * Extended Memory
- * zero length marker for end of map
- *
- * Returns are 0 for failure and 1 for success on extracting region.
- */
-int __init voyager_memory_detect(int region, __u32 * start, __u32 * length)
-{
- int i;
- int retval = 0;
- __u8 cmos[4];
- ClickMap_t *map;
- unsigned long map_addr;
- unsigned long old;
-
- if (region >= CLICK_ENTRIES) {
- printk("Voyager: Illegal ClickMap region %d\n", region);
- return 0;
- }
-
- for (i = 0; i < sizeof(cmos); i++)
- cmos[i] =
- voyager_extended_cmos_read(VOYAGER_MEMORY_CLICKMAP + i);
-
- map_addr = *(unsigned long *)cmos;
-
- /* steal page 0 for this */
- old = pg0[0];
- pg0[0] = ((map_addr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT);
- local_flush_tlb();
- /* now clear everything out but page 0 */
- map = (ClickMap_t *) (map_addr & (~PAGE_MASK));
-
- /* zero length is the end of the clickmap */
- if (map->Entry[region].Length != 0) {
- *length = map->Entry[region].Length * CLICK_SIZE;
- *start = map->Entry[region].Address;
- retval = 1;
- }
-
- /* replace the mapping */
- pg0[0] = old;
- local_flush_tlb();
- return retval;
-}
-
-/* voyager specific handling code for timer interrupts. Used to hand
- * off the timer tick to the SMP code, since the VIC doesn't have an
- * internal timer (The QIC does, but that's another story). */
-void voyager_timer_interrupt(void)
-{
- if ((jiffies & 0x3ff) == 0) {
-
- /* There seems to be something flaky in either
- * hardware or software that is resetting the timer 0
- * count to something much higher than it should be
- * This seems to occur in the boot sequence, just
- * before root is mounted. Therefore, every 10
- * seconds or so, we sanity check the timer zero count
- * and kick it back to where it should be.
- *
- * FIXME: This is the most awful hack yet seen. I
- * should work out exactly what is interfering with
- * the timer count settings early in the boot sequence
- * and swiftly introduce it to something sharp and
- * pointy. */
- __u16 val;
-
- spin_lock(&i8253_lock);
-
- outb_p(0x00, 0x43);
- val = inb_p(0x40);
- val |= inb(0x40) << 8;
- spin_unlock(&i8253_lock);
-
- if (val > LATCH) {
- printk
- ("\nVOYAGER: countdown timer value too high (%d), resetting\n\n",
- val);
- spin_lock(&i8253_lock);
- outb(0x34, 0x43);
- outb_p(LATCH & 0xff, 0x40); /* LSB */
- outb(LATCH >> 8, 0x40); /* MSB */
- spin_unlock(&i8253_lock);
- }
- }
-#ifdef CONFIG_SMP
- smp_vic_timer_interrupt();
-#endif
-}
-
-void voyager_power_off(void)
-{
- printk("VOYAGER Power Off\n");
-
- if (voyager_level == 5) {
- voyager_cat_power_off();
- } else if (voyager_level == 4) {
- /* This doesn't apparently work on most L4 machines,
- * but the specs say to do this to get automatic power
- * off. Unfortunately, if it doesn't power off the
- * machine, it ends up doing a cold restart, which
- * isn't really intended, so comment out the code */
-#if 0
- int port;
-
- /* enable the voyager Configuration Space */
- outb((inb(VOYAGER_MC_SETUP) & 0xf0) | 0x8, VOYAGER_MC_SETUP);
- /* the port for the power off flag is an offset from the
- floating base */
- port = (inb(VOYAGER_SSPB_RELOCATION_PORT) << 8) + 0x21;
- /* set the power off flag */
- outb(inb(port) | 0x1, port);
-#endif
- }
- /* and wait for it to happen */
- local_irq_disable();
- for (;;)
- halt();
-}
-
-/* copied from process.c */
-static inline void kb_wait(void)
-{
- int i;
-
- for (i = 0; i < 0x10000; i++)
- if ((inb_p(0x64) & 0x02) == 0)
- break;
-}
-
-void machine_shutdown(void)
-{
- /* Architecture specific shutdown needed before a kexec */
-}
-
-void machine_restart(char *cmd)
-{
- printk("Voyager Warm Restart\n");
- kb_wait();
-
- if (voyager_level == 5) {
- /* write magic values to the RTC to inform system that
- * shutdown is beginning */
- outb(0x8f, 0x70);
- outb(0x5, 0x71);
-
- udelay(50);
- outb(0xfe, 0x64); /* pull reset low */
- } else if (voyager_level == 4) {
- __u16 catbase = inb(VOYAGER_SSPB_RELOCATION_PORT) << 8;
- __u8 basebd = inb(VOYAGER_MC_SETUP);
-
- outb(basebd | 0x08, VOYAGER_MC_SETUP);
- outb(0x02, catbase + 0x21);
- }
- local_irq_disable();
- for (;;)
- halt();
-}
-
-void machine_emergency_restart(void)
-{
- /*for now, just hook this to a warm restart */
- machine_restart(NULL);
-}
-
-void mca_nmi_hook(void)
-{
- __u8 dumpval __maybe_unused = inb(0xf823);
- __u8 swnmi __maybe_unused = inb(0xf813);
-
- /* FIXME: assume dump switch pressed */
- /* check to see if the dump switch was pressed */
- VDEBUG(("VOYAGER: dumpval = 0x%x, swnmi = 0x%x\n", dumpval, swnmi));
- /* clear swnmi */
- outb(0xff, 0xf813);
- /* tell SUS to ignore dump */
- if (voyager_level == 5 && voyager_SUS != NULL) {
- if (voyager_SUS->SUS_mbox == VOYAGER_DUMP_BUTTON_NMI) {
- voyager_SUS->kernel_mbox = VOYAGER_NO_COMMAND;
- voyager_SUS->kernel_flags |= VOYAGER_OS_IN_PROGRESS;
- udelay(1000);
- voyager_SUS->kernel_mbox = VOYAGER_IGNORE_DUMP;
- voyager_SUS->kernel_flags &= ~VOYAGER_OS_IN_PROGRESS;
- }
- }
- printk(KERN_ERR
- "VOYAGER: Dump switch pressed, printing CPU%d tracebacks\n",
- smp_processor_id());
- show_stack(NULL, NULL);
- show_state();
-}
-
-void machine_halt(void)
-{
- /* treat a halt like a power off */
- machine_power_off();
-}
-
-void machine_power_off(void)
-{
- if (pm_power_off)
- pm_power_off();
-}
diff --git a/arch/x86/mach-voyager/voyager_cat.c b/arch/x86/mach-voyager/voyager_cat.c
deleted file mode 100644
index 2ad598c104af..000000000000
--- a/arch/x86/mach-voyager/voyager_cat.c
+++ /dev/null
@@ -1,1197 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 1999,2001
- *
- * Author: J.E.J.Bottomley@HansenPartnership.com
- *
- * This file contains all the logic for manipulating the CAT bus
- * in a level 5 machine.
- *
- * The CAT bus is a serial configuration and test bus. Its primary
- * uses are to probe the initial configuration of the system and to
- * diagnose error conditions when a system interrupt occurs. The low
- * level interface is fairly primitive, so most of this file consists
- * of bit shift manipulations to send and receive packets on the
- * serial bus */
-
-#include <linux/types.h>
-#include <linux/completion.h>
-#include <linux/sched.h>
-#include <asm/voyager.h>
-#include <asm/vic.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-
-#ifdef VOYAGER_CAT_DEBUG
-#define CDEBUG(x) printk x
-#else
-#define CDEBUG(x)
-#endif
-
-/* the CAT command port */
-#define CAT_CMD (sspb + 0xe)
-/* the CAT data port */
-#define CAT_DATA (sspb + 0xd)
-
-/* the internal cat functions */
-static void cat_pack(__u8 * msg, __u16 start_bit, __u8 * data, __u16 num_bits);
-static void cat_unpack(__u8 * msg, __u16 start_bit, __u8 * data,
- __u16 num_bits);
-static void cat_build_header(__u8 * header, const __u16 len,
- const __u16 smallest_reg_bits,
- const __u16 longest_reg_bits);
-static int cat_sendinst(voyager_module_t * modp, voyager_asic_t * asicp,
- __u8 reg, __u8 op);
-static int cat_getdata(voyager_module_t * modp, voyager_asic_t * asicp,
- __u8 reg, __u8 * value);
-static int cat_shiftout(__u8 * data, __u16 data_bytes, __u16 header_bytes,
- __u8 pad_bits);
-static int cat_write(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg,
- __u8 value);
-static int cat_read(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg,
- __u8 * value);
-static int cat_subread(voyager_module_t * modp, voyager_asic_t * asicp,
- __u16 offset, __u16 len, void *buf);
-static int cat_senddata(voyager_module_t * modp, voyager_asic_t * asicp,
- __u8 reg, __u8 value);
-static int cat_disconnect(voyager_module_t * modp, voyager_asic_t * asicp);
-static int cat_connect(voyager_module_t * modp, voyager_asic_t * asicp);
-
-static inline const char *cat_module_name(int module_id)
-{
- switch (module_id) {
- case 0x10:
- return "Processor Slot 0";
- case 0x11:
- return "Processor Slot 1";
- case 0x12:
- return "Processor Slot 2";
- case 0x13:
- return "Processor Slot 4";
- case 0x14:
- return "Memory Slot 0";
- case 0x15:
- return "Memory Slot 1";
- case 0x18:
- return "Primary Microchannel";
- case 0x19:
- return "Secondary Microchannel";
- case 0x1a:
- return "Power Supply Interface";
- case 0x1c:
- return "Processor Slot 5";
- case 0x1d:
- return "Processor Slot 6";
- case 0x1e:
- return "Processor Slot 7";
- case 0x1f:
- return "Processor Slot 8";
- default:
- return "Unknown Module";
- }
-}
-
-static int sspb = 0; /* stores the super port location */
-int voyager_8slot = 0; /* set to true if a 51xx monster */
-
-voyager_module_t *voyager_cat_list;
-
-/* the I/O port assignments for the VIC and QIC */
-static struct resource vic_res = {
- .name = "Voyager Interrupt Controller",
- .start = 0xFC00,
- .end = 0xFC6F
-};
-static struct resource qic_res = {
- .name = "Quad Interrupt Controller",
- .start = 0xFC70,
- .end = 0xFCFF
-};
-
-/* This function is used to pack a data bit stream inside a message.
- * It writes num_bits of the data buffer in msg starting at start_bit.
- * Note: This function assumes that any unused bit in the data stream
- * is set to zero so that the ors will work correctly */
-static void
-cat_pack(__u8 * msg, const __u16 start_bit, __u8 * data, const __u16 num_bits)
-{
- /* compute initial shift needed */
- const __u16 offset = start_bit % BITS_PER_BYTE;
- __u16 len = num_bits / BITS_PER_BYTE;
- __u16 byte = start_bit / BITS_PER_BYTE;
- __u16 residue = (num_bits % BITS_PER_BYTE) + offset;
- int i;
-
- /* adjust if we have more than a byte of residue */
- if (residue >= BITS_PER_BYTE) {
- residue -= BITS_PER_BYTE;
- len++;
- }
-
- /* clear out the bits. We assume here that if len==0 then
- * residue >= offset. This is always true for the catbus
- * operations */
- msg[byte] &= 0xff << (BITS_PER_BYTE - offset);
- msg[byte++] |= data[0] >> offset;
- if (len == 0)
- return;
- for (i = 1; i < len; i++)
- msg[byte++] = (data[i - 1] << (BITS_PER_BYTE - offset))
- | (data[i] >> offset);
- if (residue != 0) {
- __u8 mask = 0xff >> residue;
- __u8 last_byte = data[i - 1] << (BITS_PER_BYTE - offset)
- | (data[i] >> offset);
-
- last_byte &= ~mask;
- msg[byte] &= mask;
- msg[byte] |= last_byte;
- }
- return;
-}
-
-/* unpack the data again (same arguments as cat_pack()). data buffer
- * must be zero populated.
- *
- * Function: given a message string move to start_bit and copy num_bits into
- * data (starting at bit 0 in data).
- */
-static void
-cat_unpack(__u8 * msg, const __u16 start_bit, __u8 * data, const __u16 num_bits)
-{
- /* compute initial shift needed */
- const __u16 offset = start_bit % BITS_PER_BYTE;
- __u16 len = num_bits / BITS_PER_BYTE;
- const __u8 last_bits = num_bits % BITS_PER_BYTE;
- __u16 byte = start_bit / BITS_PER_BYTE;
- int i;
-
- if (last_bits != 0)
- len++;
-
- /* special case: want < 8 bits from msg and we can get it from
- * a single byte of the msg */
- if (len == 0 && BITS_PER_BYTE - offset >= num_bits) {
- data[0] = msg[byte] << offset;
- data[0] &= 0xff >> (BITS_PER_BYTE - num_bits);
- return;
- }
- for (i = 0; i < len; i++) {
- /* this annoying if has to be done just in case a read of
- * msg one beyond the array causes a panic */
- if (offset != 0) {
- data[i] = msg[byte++] << offset;
- data[i] |= msg[byte] >> (BITS_PER_BYTE - offset);
- } else {
- data[i] = msg[byte++];
- }
- }
- /* do we need to truncate the final byte */
- if (last_bits != 0) {
- data[i - 1] &= 0xff << (BITS_PER_BYTE - last_bits);
- }
- return;
-}
-
-static void
-cat_build_header(__u8 * header, const __u16 len, const __u16 smallest_reg_bits,
- const __u16 longest_reg_bits)
-{
- int i;
- __u16 start_bit = (smallest_reg_bits - 1) % BITS_PER_BYTE;
- __u8 *last_byte = &header[len - 1];
-
- if (start_bit == 0)
- start_bit = 1; /* must have at least one bit in the hdr */
-
- for (i = 0; i < len; i++)
- header[i] = 0;
-
- for (i = start_bit; i > 0; i--)
- *last_byte = ((*last_byte) << 1) + 1;
-
-}
-
-static int
-cat_sendinst(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, __u8 op)
-{
- __u8 parity, inst, inst_buf[4] = { 0 };
- __u8 iseq[VOYAGER_MAX_SCAN_PATH], hseq[VOYAGER_MAX_REG_SIZE];
- __u16 ibytes, hbytes, padbits;
- int i;
-
- /*
- * Parity is the parity of the register number + 1 (READ_REGISTER
- * and WRITE_REGISTER always add '1' to the number of bits == 1)
- */
- parity = (__u8) (1 + (reg & 0x01) +
- ((__u8) (reg & 0x02) >> 1) +
- ((__u8) (reg & 0x04) >> 2) +
- ((__u8) (reg & 0x08) >> 3)) % 2;
-
- inst = ((parity << 7) | (reg << 2) | op);
-
- outb(VOYAGER_CAT_IRCYC, CAT_CMD);
- if (!modp->scan_path_connected) {
- if (asicp->asic_id != VOYAGER_CAT_ID) {
- printk
- ("**WARNING***: cat_sendinst has disconnected scan path not to CAT asic\n");
- return 1;
- }
- outb(VOYAGER_CAT_HEADER, CAT_DATA);
- outb(inst, CAT_DATA);
- if (inb(CAT_DATA) != VOYAGER_CAT_HEADER) {
- CDEBUG(("VOYAGER CAT: cat_sendinst failed to get CAT_HEADER\n"));
- return 1;
- }
- return 0;
- }
- ibytes = modp->inst_bits / BITS_PER_BYTE;
- if ((padbits = modp->inst_bits % BITS_PER_BYTE) != 0) {
- padbits = BITS_PER_BYTE - padbits;
- ibytes++;
- }
- hbytes = modp->largest_reg / BITS_PER_BYTE;
- if (modp->largest_reg % BITS_PER_BYTE)
- hbytes++;
- CDEBUG(("cat_sendinst: ibytes=%d, hbytes=%d\n", ibytes, hbytes));
- /* initialise the instruction sequence to 0xff */
- for (i = 0; i < ibytes + hbytes; i++)
- iseq[i] = 0xff;
- cat_build_header(hseq, hbytes, modp->smallest_reg, modp->largest_reg);
- cat_pack(iseq, modp->inst_bits, hseq, hbytes * BITS_PER_BYTE);
- inst_buf[0] = inst;
- inst_buf[1] = 0xFF >> (modp->largest_reg % BITS_PER_BYTE);
- cat_pack(iseq, asicp->bit_location, inst_buf, asicp->ireg_length);
-#ifdef VOYAGER_CAT_DEBUG
- printk("ins = 0x%x, iseq: ", inst);
- for (i = 0; i < ibytes + hbytes; i++)
- printk("0x%x ", iseq[i]);
- printk("\n");
-#endif
- if (cat_shiftout(iseq, ibytes, hbytes, padbits)) {
- CDEBUG(("VOYAGER CAT: cat_sendinst: cat_shiftout failed\n"));
- return 1;
- }
- CDEBUG(("CAT SHIFTOUT DONE\n"));
- return 0;
-}
-
-static int
-cat_getdata(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg,
- __u8 * value)
-{
- if (!modp->scan_path_connected) {
- if (asicp->asic_id != VOYAGER_CAT_ID) {
- CDEBUG(("VOYAGER CAT: ERROR: cat_getdata to CAT asic with scan path connected\n"));
- return 1;
- }
- if (reg > VOYAGER_SUBADDRHI)
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- outb(VOYAGER_CAT_DRCYC, CAT_CMD);
- outb(VOYAGER_CAT_HEADER, CAT_DATA);
- *value = inb(CAT_DATA);
- outb(0xAA, CAT_DATA);
- if (inb(CAT_DATA) != VOYAGER_CAT_HEADER) {
- CDEBUG(("cat_getdata: failed to get VOYAGER_CAT_HEADER\n"));
- return 1;
- }
- return 0;
- } else {
- __u16 sbits = modp->num_asics - 1 + asicp->ireg_length;
- __u16 sbytes = sbits / BITS_PER_BYTE;
- __u16 tbytes;
- __u8 string[VOYAGER_MAX_SCAN_PATH],
- trailer[VOYAGER_MAX_REG_SIZE];
- __u8 padbits;
- int i;
-
- outb(VOYAGER_CAT_DRCYC, CAT_CMD);
-
- if ((padbits = sbits % BITS_PER_BYTE) != 0) {
- padbits = BITS_PER_BYTE - padbits;
- sbytes++;
- }
- tbytes = asicp->ireg_length / BITS_PER_BYTE;
- if (asicp->ireg_length % BITS_PER_BYTE)
- tbytes++;
- CDEBUG(("cat_getdata: tbytes = %d, sbytes = %d, padbits = %d\n",
- tbytes, sbytes, padbits));
- cat_build_header(trailer, tbytes, 1, asicp->ireg_length);
-
- for (i = tbytes - 1; i >= 0; i--) {
- outb(trailer[i], CAT_DATA);
- string[sbytes + i] = inb(CAT_DATA);
- }
-
- for (i = sbytes - 1; i >= 0; i--) {
- outb(0xaa, CAT_DATA);
- string[i] = inb(CAT_DATA);
- }
- *value = 0;
- cat_unpack(string,
- padbits + (tbytes * BITS_PER_BYTE) +
- asicp->asic_location, value, asicp->ireg_length);
-#ifdef VOYAGER_CAT_DEBUG
- printk("value=0x%x, string: ", *value);
- for (i = 0; i < tbytes + sbytes; i++)
- printk("0x%x ", string[i]);
- printk("\n");
-#endif
-
- /* sanity check the rest of the return */
- for (i = 0; i < tbytes; i++) {
- __u8 input = 0;
-
- cat_unpack(string, padbits + (i * BITS_PER_BYTE),
- &input, BITS_PER_BYTE);
- if (trailer[i] != input) {
- CDEBUG(("cat_getdata: failed to sanity check rest of ret(%d) 0x%x != 0x%x\n", i, input, trailer[i]));
- return 1;
- }
- }
- CDEBUG(("cat_getdata DONE\n"));
- return 0;
- }
-}
-
-static int
-cat_shiftout(__u8 * data, __u16 data_bytes, __u16 header_bytes, __u8 pad_bits)
-{
- int i;
-
- for (i = data_bytes + header_bytes - 1; i >= header_bytes; i--)
- outb(data[i], CAT_DATA);
-
- for (i = header_bytes - 1; i >= 0; i--) {
- __u8 header = 0;
- __u8 input;
-
- outb(data[i], CAT_DATA);
- input = inb(CAT_DATA);
- CDEBUG(("cat_shiftout: returned 0x%x\n", input));
- cat_unpack(data, ((data_bytes + i) * BITS_PER_BYTE) - pad_bits,
- &header, BITS_PER_BYTE);
- if (input != header) {
- CDEBUG(("VOYAGER CAT: cat_shiftout failed to return header 0x%x != 0x%x\n", input, header));
- return 1;
- }
- }
- return 0;
-}
-
-static int
-cat_senddata(voyager_module_t * modp, voyager_asic_t * asicp,
- __u8 reg, __u8 value)
-{
- outb(VOYAGER_CAT_DRCYC, CAT_CMD);
- if (!modp->scan_path_connected) {
- if (asicp->asic_id != VOYAGER_CAT_ID) {
- CDEBUG(("VOYAGER CAT: ERROR: scan path disconnected when asic != CAT\n"));
- return 1;
- }
- outb(VOYAGER_CAT_HEADER, CAT_DATA);
- outb(value, CAT_DATA);
- if (inb(CAT_DATA) != VOYAGER_CAT_HEADER) {
- CDEBUG(("cat_senddata: failed to get correct header response to sent data\n"));
- return 1;
- }
- if (reg > VOYAGER_SUBADDRHI) {
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- outb(VOYAGER_CAT_END, CAT_CMD);
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- }
-
- return 0;
- } else {
- __u16 hbytes = asicp->ireg_length / BITS_PER_BYTE;
- __u16 dbytes =
- (modp->num_asics - 1 + asicp->ireg_length) / BITS_PER_BYTE;
- __u8 padbits, dseq[VOYAGER_MAX_SCAN_PATH],
- hseq[VOYAGER_MAX_REG_SIZE];
- int i;
-
- if ((padbits = (modp->num_asics - 1
- + asicp->ireg_length) % BITS_PER_BYTE) != 0) {
- padbits = BITS_PER_BYTE - padbits;
- dbytes++;
- }
- if (asicp->ireg_length % BITS_PER_BYTE)
- hbytes++;
-
- cat_build_header(hseq, hbytes, 1, asicp->ireg_length);
-
- for (i = 0; i < dbytes + hbytes; i++)
- dseq[i] = 0xff;
- CDEBUG(("cat_senddata: dbytes=%d, hbytes=%d, padbits=%d\n",
- dbytes, hbytes, padbits));
- cat_pack(dseq, modp->num_asics - 1 + asicp->ireg_length,
- hseq, hbytes * BITS_PER_BYTE);
- cat_pack(dseq, asicp->asic_location, &value,
- asicp->ireg_length);
-#ifdef VOYAGER_CAT_DEBUG
- printk("dseq ");
- for (i = 0; i < hbytes + dbytes; i++) {
- printk("0x%x ", dseq[i]);
- }
- printk("\n");
-#endif
- return cat_shiftout(dseq, dbytes, hbytes, padbits);
- }
-}
-
-static int
-cat_write(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg, __u8 value)
-{
- if (cat_sendinst(modp, asicp, reg, VOYAGER_WRITE_CONFIG))
- return 1;
- return cat_senddata(modp, asicp, reg, value);
-}
-
-static int
-cat_read(voyager_module_t * modp, voyager_asic_t * asicp, __u8 reg,
- __u8 * value)
-{
- if (cat_sendinst(modp, asicp, reg, VOYAGER_READ_CONFIG))
- return 1;
- return cat_getdata(modp, asicp, reg, value);
-}
-
-static int
-cat_subaddrsetup(voyager_module_t * modp, voyager_asic_t * asicp, __u16 offset,
- __u16 len)
-{
- __u8 val;
-
- if (len > 1) {
- /* set auto increment */
- __u8 newval;
-
- if (cat_read(modp, asicp, VOYAGER_AUTO_INC_REG, &val)) {
- CDEBUG(("cat_subaddrsetup: read of VOYAGER_AUTO_INC_REG failed\n"));
- return 1;
- }
- CDEBUG(("cat_subaddrsetup: VOYAGER_AUTO_INC_REG = 0x%x\n",
- val));
- newval = val | VOYAGER_AUTO_INC;
- if (newval != val) {
- if (cat_write(modp, asicp, VOYAGER_AUTO_INC_REG, val)) {
- CDEBUG(("cat_subaddrsetup: write to VOYAGER_AUTO_INC_REG failed\n"));
- return 1;
- }
- }
- }
- if (cat_write(modp, asicp, VOYAGER_SUBADDRLO, (__u8) (offset & 0xff))) {
- CDEBUG(("cat_subaddrsetup: write to SUBADDRLO failed\n"));
- return 1;
- }
- if (asicp->subaddr > VOYAGER_SUBADDR_LO) {
- if (cat_write
- (modp, asicp, VOYAGER_SUBADDRHI, (__u8) (offset >> 8))) {
- CDEBUG(("cat_subaddrsetup: write to SUBADDRHI failed\n"));
- return 1;
- }
- cat_read(modp, asicp, VOYAGER_SUBADDRHI, &val);
- CDEBUG(("cat_subaddrsetup: offset = %d, hi = %d\n", offset,
- val));
- }
- cat_read(modp, asicp, VOYAGER_SUBADDRLO, &val);
- CDEBUG(("cat_subaddrsetup: offset = %d, lo = %d\n", offset, val));
- return 0;
-}
-
-static int
-cat_subwrite(voyager_module_t * modp, voyager_asic_t * asicp, __u16 offset,
- __u16 len, void *buf)
-{
- int i, retval;
-
- /* FIXME: need special actions for VOYAGER_CAT_ID here */
- if (asicp->asic_id == VOYAGER_CAT_ID) {
- CDEBUG(("cat_subwrite: ATTEMPT TO WRITE TO CAT ASIC\n"));
- /* FIXME -- This is supposed to be handled better
- * There is a problem writing to the cat asic in the
- * PSI. The 30us delay seems to work, though */
- udelay(30);
- }
-
- if ((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) {
- printk("cat_subwrite: cat_subaddrsetup FAILED\n");
- return retval;
- }
-
- if (cat_sendinst
- (modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_WRITE_CONFIG)) {
- printk("cat_subwrite: cat_sendinst FAILED\n");
- return 1;
- }
- for (i = 0; i < len; i++) {
- if (cat_senddata(modp, asicp, 0xFF, ((__u8 *) buf)[i])) {
- printk
- ("cat_subwrite: cat_sendata element at %d FAILED\n",
- i);
- return 1;
- }
- }
- return 0;
-}
-static int
-cat_subread(voyager_module_t * modp, voyager_asic_t * asicp, __u16 offset,
- __u16 len, void *buf)
-{
- int i, retval;
-
- if ((retval = cat_subaddrsetup(modp, asicp, offset, len)) != 0) {
- CDEBUG(("cat_subread: cat_subaddrsetup FAILED\n"));
- return retval;
- }
-
- if (cat_sendinst(modp, asicp, VOYAGER_SUBADDRDATA, VOYAGER_READ_CONFIG)) {
- CDEBUG(("cat_subread: cat_sendinst failed\n"));
- return 1;
- }
- for (i = 0; i < len; i++) {
- if (cat_getdata(modp, asicp, 0xFF, &((__u8 *) buf)[i])) {
- CDEBUG(("cat_subread: cat_getdata element %d failed\n",
- i));
- return 1;
- }
- }
- return 0;
-}
-
-/* buffer for storing EPROM data read in during initialisation */
-static __initdata __u8 eprom_buf[0xFFFF];
-static voyager_module_t *voyager_initial_module;
-
-/* Initialise the cat bus components. We assume this is called by the
- * boot cpu *after* all memory initialisation has been done (so we can
- * use kmalloc) but before smp initialisation, so we can probe the SMP
- * configuration and pick up necessary information. */
-void __init voyager_cat_init(void)
-{
- voyager_module_t **modpp = &voyager_initial_module;
- voyager_asic_t **asicpp;
- voyager_asic_t *qabc_asic = NULL;
- int i, j;
- unsigned long qic_addr = 0;
- __u8 qabc_data[0x20];
- __u8 num_submodules, val;
- voyager_eprom_hdr_t *eprom_hdr = (voyager_eprom_hdr_t *) & eprom_buf[0];
-
- __u8 cmos[4];
- unsigned long addr;
-
- /* initiallise the SUS mailbox */
- for (i = 0; i < sizeof(cmos); i++)
- cmos[i] = voyager_extended_cmos_read(VOYAGER_DUMP_LOCATION + i);
- addr = *(unsigned long *)cmos;
- if ((addr & 0xff000000) != 0xff000000) {
- printk(KERN_ERR
- "Voyager failed to get SUS mailbox (addr = 0x%lx\n",
- addr);
- } else {
- static struct resource res;
-
- res.name = "voyager SUS";
- res.start = addr;
- res.end = addr + 0x3ff;
-
- request_resource(&iomem_resource, &res);
- voyager_SUS = (struct voyager_SUS *)
- ioremap(addr, 0x400);
- printk(KERN_NOTICE "Voyager SUS mailbox version 0x%x\n",
- voyager_SUS->SUS_version);
- voyager_SUS->kernel_version = VOYAGER_MAILBOX_VERSION;
- voyager_SUS->kernel_flags = VOYAGER_OS_HAS_SYSINT;
- }
-
- /* clear the processor counts */
- voyager_extended_vic_processors = 0;
- voyager_quad_processors = 0;
-
- printk("VOYAGER: beginning CAT bus probe\n");
- /* set up the SuperSet Port Block which tells us where the
- * CAT communication port is */
- sspb = inb(VOYAGER_SSPB_RELOCATION_PORT) * 0x100;
- VDEBUG(("VOYAGER DEBUG: sspb = 0x%x\n", sspb));
-
- /* now find out if were 8 slot or normal */
- if ((inb(VIC_PROC_WHO_AM_I) & EIGHT_SLOT_IDENTIFIER)
- == EIGHT_SLOT_IDENTIFIER) {
- voyager_8slot = 1;
- printk(KERN_NOTICE
- "Voyager: Eight slot 51xx configuration detected\n");
- }
-
- for (i = VOYAGER_MIN_MODULE; i <= VOYAGER_MAX_MODULE; i++) {
- __u8 input;
- int asic;
- __u16 eprom_size;
- __u16 sp_offset;
-
- outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT);
- outb(i, VOYAGER_CAT_CONFIG_PORT);
-
- /* check the presence of the module */
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- outb(VOYAGER_CAT_IRCYC, CAT_CMD);
- outb(VOYAGER_CAT_HEADER, CAT_DATA);
- /* stream series of alternating 1's and 0's to stimulate
- * response */
- outb(0xAA, CAT_DATA);
- input = inb(CAT_DATA);
- outb(VOYAGER_CAT_END, CAT_CMD);
- if (input != VOYAGER_CAT_HEADER) {
- continue;
- }
- CDEBUG(("VOYAGER DEBUG: found module id 0x%x, %s\n", i,
- cat_module_name(i)));
- *modpp = kmalloc(sizeof(voyager_module_t), GFP_KERNEL); /*&voyager_module_storage[cat_count++]; */
- if (*modpp == NULL) {
- printk("**WARNING** kmalloc failure in cat_init\n");
- continue;
- }
- memset(*modpp, 0, sizeof(voyager_module_t));
- /* need temporary asic for cat_subread. It will be
- * filled in correctly later */
- (*modpp)->asic = kmalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count]; */
- if ((*modpp)->asic == NULL) {
- printk("**WARNING** kmalloc failure in cat_init\n");
- continue;
- }
- memset((*modpp)->asic, 0, sizeof(voyager_asic_t));
- (*modpp)->asic->asic_id = VOYAGER_CAT_ID;
- (*modpp)->asic->subaddr = VOYAGER_SUBADDR_HI;
- (*modpp)->module_addr = i;
- (*modpp)->scan_path_connected = 0;
- if (i == VOYAGER_PSI) {
- /* Exception leg for modules with no EEPROM */
- printk("Module \"%s\"\n", cat_module_name(i));
- continue;
- }
-
- CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i, VOYAGER_XSUM_END_OFFSET));
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_disconnect(*modpp, (*modpp)->asic);
- if (cat_subread(*modpp, (*modpp)->asic,
- VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size),
- &eprom_size)) {
- printk
- ("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n",
- i);
- outb(VOYAGER_CAT_END, CAT_CMD);
- continue;
- }
- if (eprom_size > sizeof(eprom_buf)) {
- printk
- ("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n",
- i, eprom_size);
- outb(VOYAGER_CAT_END, CAT_CMD);
- continue;
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i,
- eprom_size));
- if (cat_subread
- (*modpp, (*modpp)->asic, 0, eprom_size, eprom_buf)) {
- outb(VOYAGER_CAT_END, CAT_CMD);
- continue;
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
- printk("Module \"%s\", version 0x%x, tracer 0x%x, asics %d\n",
- cat_module_name(i), eprom_hdr->version_id,
- *((__u32 *) eprom_hdr->tracer), eprom_hdr->num_asics);
- (*modpp)->ee_size = eprom_hdr->ee_size;
- (*modpp)->num_asics = eprom_hdr->num_asics;
- asicpp = &((*modpp)->asic);
- sp_offset = eprom_hdr->scan_path_offset;
- /* All we really care about are the Quad cards. We
- * identify them because they are in a processor slot
- * and have only four asics */
- if ((i < 0x10 || (i >= 0x14 && i < 0x1c) || i > 0x1f)) {
- modpp = &((*modpp)->next);
- continue;
- }
- /* Now we know it's in a processor slot, does it have
- * a quad baseboard submodule */
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_read(*modpp, (*modpp)->asic, VOYAGER_SUBMODPRESENT,
- &num_submodules);
- /* lowest two bits, active low */
- num_submodules = ~(0xfc | num_submodules);
- CDEBUG(("VOYAGER CAT: %d submodules present\n",
- num_submodules));
- if (num_submodules == 0) {
- /* fill in the dyadic extended processors */
- __u8 cpu = i & 0x07;
-
- printk("Module \"%s\": Dyadic Processor Card\n",
- cat_module_name(i));
- voyager_extended_vic_processors |= (1 << cpu);
- cpu += 4;
- voyager_extended_vic_processors |= (1 << cpu);
- outb(VOYAGER_CAT_END, CAT_CMD);
- continue;
- }
-
- /* now we want to read the asics on the first submodule,
- * which should be the quad base board */
-
- cat_read(*modpp, (*modpp)->asic, VOYAGER_SUBMODSELECT, &val);
- CDEBUG(("cat_init: SUBMODSELECT value = 0x%x\n", val));
- val = (val & 0x7c) | VOYAGER_QUAD_BASEBOARD;
- cat_write(*modpp, (*modpp)->asic, VOYAGER_SUBMODSELECT, val);
-
- outb(VOYAGER_CAT_END, CAT_CMD);
-
- CDEBUG(("cat_init: Reading eeprom for module 0x%x at offset %d\n", i, VOYAGER_XSUM_END_OFFSET));
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_disconnect(*modpp, (*modpp)->asic);
- if (cat_subread(*modpp, (*modpp)->asic,
- VOYAGER_XSUM_END_OFFSET, sizeof(eprom_size),
- &eprom_size)) {
- printk
- ("**WARNING**: Voyager couldn't read EPROM size for module 0x%x\n",
- i);
- outb(VOYAGER_CAT_END, CAT_CMD);
- continue;
- }
- if (eprom_size > sizeof(eprom_buf)) {
- printk
- ("**WARNING**: Voyager insufficient size to read EPROM data, module 0x%x. Need %d\n",
- i, eprom_size);
- outb(VOYAGER_CAT_END, CAT_CMD);
- continue;
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- CDEBUG(("cat_init: module 0x%x, eeprom_size %d\n", i,
- eprom_size));
- if (cat_subread
- (*modpp, (*modpp)->asic, 0, eprom_size, eprom_buf)) {
- outb(VOYAGER_CAT_END, CAT_CMD);
- continue;
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
- /* Now do everything for the QBB submodule 1 */
- (*modpp)->ee_size = eprom_hdr->ee_size;
- (*modpp)->num_asics = eprom_hdr->num_asics;
- asicpp = &((*modpp)->asic);
- sp_offset = eprom_hdr->scan_path_offset;
- /* get rid of the dummy CAT asic and read the real one */
- kfree((*modpp)->asic);
- for (asic = 0; asic < (*modpp)->num_asics; asic++) {
- int j;
- voyager_asic_t *asicp = *asicpp = kzalloc(sizeof(voyager_asic_t), GFP_KERNEL); /*&voyager_asic_storage[asic_count++]; */
- voyager_sp_table_t *sp_table;
- voyager_at_t *asic_table;
- voyager_jtt_t *jtag_table;
-
- if (asicp == NULL) {
- printk
- ("**WARNING** kmalloc failure in cat_init\n");
- continue;
- }
- asicpp = &(asicp->next);
- asicp->asic_location = asic;
- sp_table =
- (voyager_sp_table_t *) (eprom_buf + sp_offset);
- asicp->asic_id = sp_table->asic_id;
- asic_table =
- (voyager_at_t *) (eprom_buf +
- sp_table->asic_data_offset);
- for (j = 0; j < 4; j++)
- asicp->jtag_id[j] = asic_table->jtag_id[j];
- jtag_table =
- (voyager_jtt_t *) (eprom_buf +
- asic_table->jtag_offset);
- asicp->ireg_length = jtag_table->ireg_len;
- asicp->bit_location = (*modpp)->inst_bits;
- (*modpp)->inst_bits += asicp->ireg_length;
- if (asicp->ireg_length > (*modpp)->largest_reg)
- (*modpp)->largest_reg = asicp->ireg_length;
- if (asicp->ireg_length < (*modpp)->smallest_reg ||
- (*modpp)->smallest_reg == 0)
- (*modpp)->smallest_reg = asicp->ireg_length;
- CDEBUG(("asic 0x%x, ireg_length=%d, bit_location=%d\n",
- asicp->asic_id, asicp->ireg_length,
- asicp->bit_location));
- if (asicp->asic_id == VOYAGER_QUAD_QABC) {
- CDEBUG(("VOYAGER CAT: QABC ASIC found\n"));
- qabc_asic = asicp;
- }
- sp_offset += sizeof(voyager_sp_table_t);
- }
- CDEBUG(("Module inst_bits = %d, largest_reg = %d, smallest_reg=%d\n", (*modpp)->inst_bits, (*modpp)->largest_reg, (*modpp)->smallest_reg));
- /* OK, now we have the QUAD ASICs set up, use them.
- * we need to:
- *
- * 1. Find the Memory area for the Quad CPIs.
- * 2. Find the Extended VIC processor
- * 3. Configure a second extended VIC processor (This
- * cannot be done for the 51xx.
- * */
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_connect(*modpp, (*modpp)->asic);
- CDEBUG(("CAT CONNECTED!!\n"));
- cat_subread(*modpp, qabc_asic, 0, sizeof(qabc_data), qabc_data);
- qic_addr = qabc_data[5] << 8;
- qic_addr = (qic_addr | qabc_data[6]) << 8;
- qic_addr = (qic_addr | qabc_data[7]) << 8;
- printk
- ("Module \"%s\": Quad Processor Card; CPI 0x%lx, SET=0x%x\n",
- cat_module_name(i), qic_addr, qabc_data[8]);
-#if 0 /* plumbing fails---FIXME */
- if ((qabc_data[8] & 0xf0) == 0) {
- /* FIXME: 32 way 8 CPU slot monster cannot be
- * plumbed this way---need to check for it */
-
- printk("Plumbing second Extended Quad Processor\n");
- /* second VIC line hardwired to Quad CPU 1 */
- qabc_data[8] |= 0x20;
- cat_subwrite(*modpp, qabc_asic, 8, 1, &qabc_data[8]);
-#ifdef VOYAGER_CAT_DEBUG
- /* verify plumbing */
- cat_subread(*modpp, qabc_asic, 8, 1, &qabc_data[8]);
- if ((qabc_data[8] & 0xf0) == 0) {
- CDEBUG(("PLUMBING FAILED: 0x%x\n",
- qabc_data[8]));
- }
-#endif
- }
-#endif
-
- {
- struct resource *res =
- kzalloc(sizeof(struct resource), GFP_KERNEL);
- res->name = kmalloc(128, GFP_KERNEL);
- sprintf((char *)res->name, "Voyager %s Quad CPI",
- cat_module_name(i));
- res->start = qic_addr;
- res->end = qic_addr + 0x3ff;
- request_resource(&iomem_resource, res);
- }
-
- qic_addr = (unsigned long)ioremap_cache(qic_addr, 0x400);
-
- for (j = 0; j < 4; j++) {
- __u8 cpu;
-
- if (voyager_8slot) {
- /* 8 slot has a different mapping,
- * each slot has only one vic line, so
- * 1 cpu in each slot must be < 8 */
- cpu = (i & 0x07) + j * 8;
- } else {
- cpu = (i & 0x03) + j * 4;
- }
- if ((qabc_data[8] & (1 << j))) {
- voyager_extended_vic_processors |= (1 << cpu);
- }
- if (qabc_data[8] & (1 << (j + 4))) {
- /* Second SET register plumbed: Quad
- * card has two VIC connected CPUs.
- * Secondary cannot be booted as a VIC
- * CPU */
- voyager_extended_vic_processors |= (1 << cpu);
- voyager_allowed_boot_processors &=
- (~(1 << cpu));
- }
-
- voyager_quad_processors |= (1 << cpu);
- voyager_quad_cpi_addr[cpu] = (struct voyager_qic_cpi *)
- (qic_addr + (j << 8));
- CDEBUG(("CPU%d: CPI address 0x%lx\n", cpu,
- (unsigned long)voyager_quad_cpi_addr[cpu]));
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
-
- *asicpp = NULL;
- modpp = &((*modpp)->next);
- }
- *modpp = NULL;
- printk
- ("CAT Bus Initialisation finished: extended procs 0x%x, quad procs 0x%x, allowed vic boot = 0x%x\n",
- voyager_extended_vic_processors, voyager_quad_processors,
- voyager_allowed_boot_processors);
- request_resource(&ioport_resource, &vic_res);
- if (voyager_quad_processors)
- request_resource(&ioport_resource, &qic_res);
- /* set up the front power switch */
-}
-
-int voyager_cat_readb(__u8 module, __u8 asic, int reg)
-{
- return 0;
-}
-
-static int cat_disconnect(voyager_module_t * modp, voyager_asic_t * asicp)
-{
- __u8 val;
- int err = 0;
-
- if (!modp->scan_path_connected)
- return 0;
- if (asicp->asic_id != VOYAGER_CAT_ID) {
- CDEBUG(("cat_disconnect: ASIC is not CAT\n"));
- return 1;
- }
- err = cat_read(modp, asicp, VOYAGER_SCANPATH, &val);
- if (err) {
- CDEBUG(("cat_disconnect: failed to read SCANPATH\n"));
- return err;
- }
- val &= VOYAGER_DISCONNECT_ASIC;
- err = cat_write(modp, asicp, VOYAGER_SCANPATH, val);
- if (err) {
- CDEBUG(("cat_disconnect: failed to write SCANPATH\n"));
- return err;
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- modp->scan_path_connected = 0;
-
- return 0;
-}
-
-static int cat_connect(voyager_module_t * modp, voyager_asic_t * asicp)
-{
- __u8 val;
- int err = 0;
-
- if (modp->scan_path_connected)
- return 0;
- if (asicp->asic_id != VOYAGER_CAT_ID) {
- CDEBUG(("cat_connect: ASIC is not CAT\n"));
- return 1;
- }
-
- err = cat_read(modp, asicp, VOYAGER_SCANPATH, &val);
- if (err) {
- CDEBUG(("cat_connect: failed to read SCANPATH\n"));
- return err;
- }
- val |= VOYAGER_CONNECT_ASIC;
- err = cat_write(modp, asicp, VOYAGER_SCANPATH, val);
- if (err) {
- CDEBUG(("cat_connect: failed to write SCANPATH\n"));
- return err;
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- modp->scan_path_connected = 1;
-
- return 0;
-}
-
-void voyager_cat_power_off(void)
-{
- /* Power the machine off by writing to the PSI over the CAT
- * bus */
- __u8 data;
- voyager_module_t psi = { 0 };
- voyager_asic_t psi_asic = { 0 };
-
- psi.asic = &psi_asic;
- psi.asic->asic_id = VOYAGER_CAT_ID;
- psi.asic->subaddr = VOYAGER_SUBADDR_HI;
- psi.module_addr = VOYAGER_PSI;
- psi.scan_path_connected = 0;
-
- outb(VOYAGER_CAT_END, CAT_CMD);
- /* Connect the PSI to the CAT Bus */
- outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT);
- outb(VOYAGER_PSI, VOYAGER_CAT_CONFIG_PORT);
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_disconnect(&psi, &psi_asic);
- /* Read the status */
- cat_subread(&psi, &psi_asic, VOYAGER_PSI_GENERAL_REG, 1, &data);
- outb(VOYAGER_CAT_END, CAT_CMD);
- CDEBUG(("PSI STATUS 0x%x\n", data));
- /* These two writes are power off prep and perform */
- data = PSI_CLEAR;
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_GENERAL_REG, 1, &data);
- outb(VOYAGER_CAT_END, CAT_CMD);
- data = PSI_POWER_DOWN;
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_GENERAL_REG, 1, &data);
- outb(VOYAGER_CAT_END, CAT_CMD);
-}
-
-struct voyager_status voyager_status = { 0 };
-
-void voyager_cat_psi(__u8 cmd, __u16 reg, __u8 * data)
-{
- voyager_module_t psi = { 0 };
- voyager_asic_t psi_asic = { 0 };
-
- psi.asic = &psi_asic;
- psi.asic->asic_id = VOYAGER_CAT_ID;
- psi.asic->subaddr = VOYAGER_SUBADDR_HI;
- psi.module_addr = VOYAGER_PSI;
- psi.scan_path_connected = 0;
-
- outb(VOYAGER_CAT_END, CAT_CMD);
- /* Connect the PSI to the CAT Bus */
- outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT);
- outb(VOYAGER_PSI, VOYAGER_CAT_CONFIG_PORT);
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_disconnect(&psi, &psi_asic);
- switch (cmd) {
- case VOYAGER_PSI_READ:
- cat_read(&psi, &psi_asic, reg, data);
- break;
- case VOYAGER_PSI_WRITE:
- cat_write(&psi, &psi_asic, reg, *data);
- break;
- case VOYAGER_PSI_SUBREAD:
- cat_subread(&psi, &psi_asic, reg, 1, data);
- break;
- case VOYAGER_PSI_SUBWRITE:
- cat_subwrite(&psi, &psi_asic, reg, 1, data);
- break;
- default:
- printk(KERN_ERR "Voyager PSI, unrecognised command %d\n", cmd);
- break;
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
-}
-
-void voyager_cat_do_common_interrupt(void)
-{
- /* This is caused either by a memory parity error or something
- * in the PSI */
- __u8 data;
- voyager_module_t psi = { 0 };
- voyager_asic_t psi_asic = { 0 };
- struct voyager_psi psi_reg;
- int i;
- re_read:
- psi.asic = &psi_asic;
- psi.asic->asic_id = VOYAGER_CAT_ID;
- psi.asic->subaddr = VOYAGER_SUBADDR_HI;
- psi.module_addr = VOYAGER_PSI;
- psi.scan_path_connected = 0;
-
- outb(VOYAGER_CAT_END, CAT_CMD);
- /* Connect the PSI to the CAT Bus */
- outb(VOYAGER_CAT_DESELECT, VOYAGER_CAT_CONFIG_PORT);
- outb(VOYAGER_PSI, VOYAGER_CAT_CONFIG_PORT);
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_disconnect(&psi, &psi_asic);
- /* Read the status. NOTE: Need to read *all* the PSI regs here
- * otherwise the cmn int will be reasserted */
- for (i = 0; i < sizeof(psi_reg.regs); i++) {
- cat_read(&psi, &psi_asic, i, &((__u8 *) & psi_reg.regs)[i]);
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
- if ((psi_reg.regs.checkbit & 0x02) == 0) {
- psi_reg.regs.checkbit |= 0x02;
- cat_write(&psi, &psi_asic, 5, psi_reg.regs.checkbit);
- printk("VOYAGER RE-READ PSI\n");
- goto re_read;
- }
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- for (i = 0; i < sizeof(psi_reg.subregs); i++) {
- /* This looks strange, but the PSI doesn't do auto increment
- * correctly */
- cat_subread(&psi, &psi_asic, VOYAGER_PSI_SUPPLY_REG + i,
- 1, &((__u8 *) & psi_reg.subregs)[i]);
- }
- outb(VOYAGER_CAT_END, CAT_CMD);
-#ifdef VOYAGER_CAT_DEBUG
- printk("VOYAGER PSI: ");
- for (i = 0; i < sizeof(psi_reg.regs); i++)
- printk("%02x ", ((__u8 *) & psi_reg.regs)[i]);
- printk("\n ");
- for (i = 0; i < sizeof(psi_reg.subregs); i++)
- printk("%02x ", ((__u8 *) & psi_reg.subregs)[i]);
- printk("\n");
-#endif
- if (psi_reg.regs.intstatus & PSI_MON) {
- /* switch off or power fail */
-
- if (psi_reg.subregs.supply & PSI_SWITCH_OFF) {
- if (voyager_status.switch_off) {
- printk(KERN_ERR
- "Voyager front panel switch turned off again---Immediate power off!\n");
- voyager_cat_power_off();
- /* not reached */
- } else {
- printk(KERN_ERR
- "Voyager front panel switch turned off\n");
- voyager_status.switch_off = 1;
- voyager_status.request_from_kernel = 1;
- wake_up_process(voyager_thread);
- }
- /* Tell the hardware we're taking care of the
- * shutdown, otherwise it will power the box off
- * within 3 seconds of the switch being pressed and,
- * which is much more important to us, continue to
- * assert the common interrupt */
- data = PSI_CLR_SWITCH_OFF;
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_SUPPLY_REG,
- 1, &data);
- outb(VOYAGER_CAT_END, CAT_CMD);
- } else {
-
- VDEBUG(("Voyager ac fail reg 0x%x\n",
- psi_reg.subregs.ACfail));
- if ((psi_reg.subregs.ACfail & AC_FAIL_STAT_CHANGE) == 0) {
- /* No further update */
- return;
- }
-#if 0
- /* Don't bother trying to find out who failed.
- * FIXME: This probably makes the code incorrect on
- * anything other than a 345x */
- for (i = 0; i < 5; i++) {
- if (psi_reg.subregs.ACfail & (1 << i)) {
- break;
- }
- }
- printk(KERN_NOTICE "AC FAIL IN SUPPLY %d\n", i);
-#endif
- /* DON'T do this: it shuts down the AC PSI
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- data = PSI_MASK_MASK | i;
- cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_MASK,
- 1, &data);
- outb(VOYAGER_CAT_END, CAT_CMD);
- */
- printk(KERN_ERR "Voyager AC power failure\n");
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- data = PSI_COLD_START;
- cat_subwrite(&psi, &psi_asic, VOYAGER_PSI_GENERAL_REG,
- 1, &data);
- outb(VOYAGER_CAT_END, CAT_CMD);
- voyager_status.power_fail = 1;
- voyager_status.request_from_kernel = 1;
- wake_up_process(voyager_thread);
- }
-
- } else if (psi_reg.regs.intstatus & PSI_FAULT) {
- /* Major fault! */
- printk(KERN_ERR
- "Voyager PSI Detected major fault, immediate power off!\n");
- voyager_cat_power_off();
- /* not reached */
- } else if (psi_reg.regs.intstatus & (PSI_DC_FAIL | PSI_ALARM
- | PSI_CURRENT | PSI_DVM
- | PSI_PSCFAULT | PSI_STAT_CHG)) {
- /* other psi fault */
-
- printk(KERN_WARNING "Voyager PSI status 0x%x\n", data);
- /* clear the PSI fault */
- outb(VOYAGER_CAT_RUN, CAT_CMD);
- cat_write(&psi, &psi_asic, VOYAGER_PSI_STATUS_REG, 0);
- outb(VOYAGER_CAT_END, CAT_CMD);
- }
-}
diff --git a/arch/x86/mach-voyager/voyager_smp.c b/arch/x86/mach-voyager/voyager_smp.c
deleted file mode 100644
index 98e3c2bc7563..000000000000
--- a/arch/x86/mach-voyager/voyager_smp.c
+++ /dev/null
@@ -1,1805 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 1999,2001
- *
- * Author: J.E.J.Bottomley@HansenPartnership.com
- *
- * This file provides all the same external entries as smp.c but uses
- * the voyager hal to provide the functionality
- */
-#include <linux/cpu.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#include <linux/mc146818rtc.h>
-#include <linux/cache.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/bootmem.h>
-#include <linux/completion.h>
-#include <asm/desc.h>
-#include <asm/voyager.h>
-#include <asm/vic.h>
-#include <asm/mtrr.h>
-#include <asm/pgalloc.h>
-#include <asm/tlbflush.h>
-#include <asm/arch_hooks.h>
-#include <asm/trampoline.h>
-
-/* TLB state -- visible externally, indexed physically */
-DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) = { &init_mm, 0 };
-
-/* CPU IRQ affinity -- set to all ones initially */
-static unsigned long cpu_irq_affinity[NR_CPUS] __cacheline_aligned =
- {[0 ... NR_CPUS-1] = ~0UL };
-
-/* per CPU data structure (for /proc/cpuinfo et al), visible externally
- * indexed physically */
-DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
-EXPORT_PER_CPU_SYMBOL(cpu_info);
-
-/* physical ID of the CPU used to boot the system */
-unsigned char boot_cpu_id;
-
-/* The memory line addresses for the Quad CPIs */
-struct voyager_qic_cpi *voyager_quad_cpi_addr[NR_CPUS] __cacheline_aligned;
-
-/* The masks for the Extended VIC processors, filled in by cat_init */
-__u32 voyager_extended_vic_processors = 0;
-
-/* Masks for the extended Quad processors which cannot be VIC booted */
-__u32 voyager_allowed_boot_processors = 0;
-
-/* The mask for the Quad Processors (both extended and non-extended) */
-__u32 voyager_quad_processors = 0;
-
-/* Total count of live CPUs, used in process.c to display
- * the CPU information and in irq.c for the per CPU irq
- * activity count. Finally exported by i386_ksyms.c */
-static int voyager_extended_cpus = 1;
-
-/* Used for the invalidate map that's also checked in the spinlock */
-static volatile unsigned long smp_invalidate_needed;
-
-/* Bitmask of CPUs present in the system - exported by i386_syms.c, used
- * by scheduler but indexed physically */
-cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
-
-/* The internal functions */
-static void send_CPI(__u32 cpuset, __u8 cpi);
-static void ack_CPI(__u8 cpi);
-static int ack_QIC_CPI(__u8 cpi);
-static void ack_special_QIC_CPI(__u8 cpi);
-static void ack_VIC_CPI(__u8 cpi);
-static void send_CPI_allbutself(__u8 cpi);
-static void mask_vic_irq(unsigned int irq);
-static void unmask_vic_irq(unsigned int irq);
-static unsigned int startup_vic_irq(unsigned int irq);
-static void enable_local_vic_irq(unsigned int irq);
-static void disable_local_vic_irq(unsigned int irq);
-static void before_handle_vic_irq(unsigned int irq);
-static void after_handle_vic_irq(unsigned int irq);
-static void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask);
-static void ack_vic_irq(unsigned int irq);
-static void vic_enable_cpi(void);
-static void do_boot_cpu(__u8 cpuid);
-static void do_quad_bootstrap(void);
-static void initialize_secondary(void);
-
-int hard_smp_processor_id(void);
-int safe_smp_processor_id(void);
-
-/* Inline functions */
-static inline void send_one_QIC_CPI(__u8 cpu, __u8 cpi)
-{
- voyager_quad_cpi_addr[cpu]->qic_cpi[cpi].cpi =
- (smp_processor_id() << 16) + cpi;
-}
-
-static inline void send_QIC_CPI(__u32 cpuset, __u8 cpi)
-{
- int cpu;
-
- for_each_online_cpu(cpu) {
- if (cpuset & (1 << cpu)) {
-#ifdef VOYAGER_DEBUG
- if (!cpu_online(cpu))
- VDEBUG(("CPU%d sending cpi %d to CPU%d not in "
- "cpu_online_map\n",
- hard_smp_processor_id(), cpi, cpu));
-#endif
- send_one_QIC_CPI(cpu, cpi - QIC_CPI_OFFSET);
- }
- }
-}
-
-static inline void wrapper_smp_local_timer_interrupt(void)
-{
- irq_enter();
- smp_local_timer_interrupt();
- irq_exit();
-}
-
-static inline void send_one_CPI(__u8 cpu, __u8 cpi)
-{
- if (voyager_quad_processors & (1 << cpu))
- send_one_QIC_CPI(cpu, cpi - QIC_CPI_OFFSET);
- else
- send_CPI(1 << cpu, cpi);
-}
-
-static inline void send_CPI_allbutself(__u8 cpi)
-{
- __u8 cpu = smp_processor_id();
- __u32 mask = cpus_addr(cpu_online_map)[0] & ~(1 << cpu);
- send_CPI(mask, cpi);
-}
-
-static inline int is_cpu_quad(void)
-{
- __u8 cpumask = inb(VIC_PROC_WHO_AM_I);
- return ((cpumask & QUAD_IDENTIFIER) == QUAD_IDENTIFIER);
-}
-
-static inline int is_cpu_extended(void)
-{
- __u8 cpu = hard_smp_processor_id();
-
- return (voyager_extended_vic_processors & (1 << cpu));
-}
-
-static inline int is_cpu_vic_boot(void)
-{
- __u8 cpu = hard_smp_processor_id();
-
- return (voyager_extended_vic_processors
- & voyager_allowed_boot_processors & (1 << cpu));
-}
-
-static inline void ack_CPI(__u8 cpi)
-{
- switch (cpi) {
- case VIC_CPU_BOOT_CPI:
- if (is_cpu_quad() && !is_cpu_vic_boot())
- ack_QIC_CPI(cpi);
- else
- ack_VIC_CPI(cpi);
- break;
- case VIC_SYS_INT:
- case VIC_CMN_INT:
- /* These are slightly strange. Even on the Quad card,
- * They are vectored as VIC CPIs */
- if (is_cpu_quad())
- ack_special_QIC_CPI(cpi);
- else
- ack_VIC_CPI(cpi);
- break;
- default:
- printk("VOYAGER ERROR: CPI%d is in common CPI code\n", cpi);
- break;
- }
-}
-
-/* local variables */
-
-/* The VIC IRQ descriptors -- these look almost identical to the
- * 8259 IRQs except that masks and things must be kept per processor
- */
-static struct irq_chip vic_chip = {
- .name = "VIC",
- .startup = startup_vic_irq,
- .mask = mask_vic_irq,
- .unmask = unmask_vic_irq,
- .set_affinity = set_vic_irq_affinity,
-};
-
-/* used to count up as CPUs are brought on line (starts at 0) */
-static int cpucount = 0;
-
-/* The per cpu profile stuff - used in smp_local_timer_interrupt */
-static DEFINE_PER_CPU(int, prof_multiplier) = 1;
-static DEFINE_PER_CPU(int, prof_old_multiplier) = 1;
-static DEFINE_PER_CPU(int, prof_counter) = 1;
-
-/* the map used to check if a CPU has booted */
-static __u32 cpu_booted_map;
-
-/* the synchronize flag used to hold all secondary CPUs spinning in
- * a tight loop until the boot sequence is ready for them */
-static cpumask_t smp_commenced_mask = CPU_MASK_NONE;
-
-/* This is for the new dynamic CPU boot code */
-
-/* The per processor IRQ masks (these are usually kept in sync) */
-static __u16 vic_irq_mask[NR_CPUS] __cacheline_aligned;
-
-/* the list of IRQs to be enabled by the VIC_ENABLE_IRQ_CPI */
-static __u16 vic_irq_enable_mask[NR_CPUS] __cacheline_aligned = { 0 };
-
-/* Lock for enable/disable of VIC interrupts */
-static __cacheline_aligned DEFINE_SPINLOCK(vic_irq_lock);
-
-/* The boot processor is correctly set up in PC mode when it
- * comes up, but the secondaries need their master/slave 8259
- * pairs initializing correctly */
-
-/* Interrupt counters (per cpu) and total - used to try to
- * even up the interrupt handling routines */
-static long vic_intr_total = 0;
-static long vic_intr_count[NR_CPUS] __cacheline_aligned = { 0 };
-static unsigned long vic_tick[NR_CPUS] __cacheline_aligned = { 0 };
-
-/* Since we can only use CPI0, we fake all the other CPIs */
-static unsigned long vic_cpi_mailbox[NR_CPUS] __cacheline_aligned;
-
-/* debugging routine to read the isr of the cpu's pic */
-static inline __u16 vic_read_isr(void)
-{
- __u16 isr;
-
- outb(0x0b, 0xa0);
- isr = inb(0xa0) << 8;
- outb(0x0b, 0x20);
- isr |= inb(0x20);
-
- return isr;
-}
-
-static __init void qic_setup(void)
-{
- if (!is_cpu_quad()) {
- /* not a quad, no setup */
- return;
- }
- outb(QIC_DEFAULT_MASK0, QIC_MASK_REGISTER0);
- outb(QIC_CPI_ENABLE, QIC_MASK_REGISTER1);
-
- if (is_cpu_extended()) {
- /* the QIC duplicate of the VIC base register */
- outb(VIC_DEFAULT_CPI_BASE, QIC_VIC_CPI_BASE_REGISTER);
- outb(QIC_DEFAULT_CPI_BASE, QIC_CPI_BASE_REGISTER);
-
- /* FIXME: should set up the QIC timer and memory parity
- * error vectors here */
- }
-}
-
-static __init void vic_setup_pic(void)
-{
- outb(1, VIC_REDIRECT_REGISTER_1);
- /* clear the claim registers for dynamic routing */
- outb(0, VIC_CLAIM_REGISTER_0);
- outb(0, VIC_CLAIM_REGISTER_1);
-
- outb(0, VIC_PRIORITY_REGISTER);
- /* Set the Primary and Secondary Microchannel vector
- * bases to be the same as the ordinary interrupts
- *
- * FIXME: This would be more efficient using separate
- * vectors. */
- outb(FIRST_EXTERNAL_VECTOR, VIC_PRIMARY_MC_BASE);
- outb(FIRST_EXTERNAL_VECTOR, VIC_SECONDARY_MC_BASE);
- /* Now initiallise the master PIC belonging to this CPU by
- * sending the four ICWs */
-
- /* ICW1: level triggered, ICW4 needed */
- outb(0x19, 0x20);
-
- /* ICW2: vector base */
- outb(FIRST_EXTERNAL_VECTOR, 0x21);
-
- /* ICW3: slave at line 2 */
- outb(0x04, 0x21);
-
- /* ICW4: 8086 mode */
- outb(0x01, 0x21);
-
- /* now the same for the slave PIC */
-
- /* ICW1: level trigger, ICW4 needed */
- outb(0x19, 0xA0);
-
- /* ICW2: slave vector base */
- outb(FIRST_EXTERNAL_VECTOR + 8, 0xA1);
-
- /* ICW3: slave ID */
- outb(0x02, 0xA1);
-
- /* ICW4: 8086 mode */
- outb(0x01, 0xA1);
-}
-
-static void do_quad_bootstrap(void)
-{
- if (is_cpu_quad() && is_cpu_vic_boot()) {
- int i;
- unsigned long flags;
- __u8 cpuid = hard_smp_processor_id();
-
- local_irq_save(flags);
-
- for (i = 0; i < 4; i++) {
- /* FIXME: this would be >>3 &0x7 on the 32 way */
- if (((cpuid >> 2) & 0x03) == i)
- /* don't lower our own mask! */
- continue;
-
- /* masquerade as local Quad CPU */
- outb(QIC_CPUID_ENABLE | i, QIC_PROCESSOR_ID);
- /* enable the startup CPI */
- outb(QIC_BOOT_CPI_MASK, QIC_MASK_REGISTER1);
- /* restore cpu id */
- outb(0, QIC_PROCESSOR_ID);
- }
- local_irq_restore(flags);
- }
-}
-
-void prefill_possible_map(void)
-{
- /* This is empty on voyager because we need a much
- * earlier detection which is done in find_smp_config */
-}
-
-/* Set up all the basic stuff: read the SMP config and make all the
- * SMP information reflect only the boot cpu. All others will be
- * brought on-line later. */
-void __init find_smp_config(void)
-{
- int i;
-
- boot_cpu_id = hard_smp_processor_id();
-
- printk("VOYAGER SMP: Boot cpu is %d\n", boot_cpu_id);
-
- /* initialize the CPU structures (moved from smp_boot_cpus) */
- for (i = 0; i < nr_cpu_ids; i++)
- cpu_irq_affinity[i] = ~0;
- cpu_online_map = cpumask_of_cpu(boot_cpu_id);
-
- /* The boot CPU must be extended */
- voyager_extended_vic_processors = 1 << boot_cpu_id;
- /* initially, all of the first 8 CPUs can boot */
- voyager_allowed_boot_processors = 0xff;
- /* set up everything for just this CPU, we can alter
- * this as we start the other CPUs later */
- /* now get the CPU disposition from the extended CMOS */
- cpus_addr(phys_cpu_present_map)[0] =
- voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK);
- cpus_addr(phys_cpu_present_map)[0] |=
- voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK + 1) << 8;
- cpus_addr(phys_cpu_present_map)[0] |=
- voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
- 2) << 16;
- cpus_addr(phys_cpu_present_map)[0] |=
- voyager_extended_cmos_read(VOYAGER_PROCESSOR_PRESENT_MASK +
- 3) << 24;
- init_cpu_possible(&phys_cpu_present_map);
- printk("VOYAGER SMP: phys_cpu_present_map = 0x%lx\n",
- cpus_addr(phys_cpu_present_map)[0]);
- /* Here we set up the VIC to enable SMP */
- /* enable the CPIs by writing the base vector to their register */
- outb(VIC_DEFAULT_CPI_BASE, VIC_CPI_BASE_REGISTER);
- outb(1, VIC_REDIRECT_REGISTER_1);
- /* set the claim registers for static routing --- Boot CPU gets
- * all interrupts untill all other CPUs started */
- outb(0xff, VIC_CLAIM_REGISTER_0);
- outb(0xff, VIC_CLAIM_REGISTER_1);
- /* Set the Primary and Secondary Microchannel vector
- * bases to be the same as the ordinary interrupts
- *
- * FIXME: This would be more efficient using separate
- * vectors. */
- outb(FIRST_EXTERNAL_VECTOR, VIC_PRIMARY_MC_BASE);
- outb(FIRST_EXTERNAL_VECTOR, VIC_SECONDARY_MC_BASE);
-
- /* Finally tell the firmware that we're driving */
- outb(inb(VOYAGER_SUS_IN_CONTROL_PORT) | VOYAGER_IN_CONTROL_FLAG,
- VOYAGER_SUS_IN_CONTROL_PORT);
-
- current_thread_info()->cpu = boot_cpu_id;
- percpu_write(cpu_number, boot_cpu_id);
-}
-
-/*
- * The bootstrap kernel entry code has set these up. Save them
- * for a given CPU, id is physical */
-void __init smp_store_cpu_info(int id)
-{
- struct cpuinfo_x86 *c = &cpu_data(id);
-
- *c = boot_cpu_data;
- c->cpu_index = id;
-
- identify_secondary_cpu(c);
-}
-
-/* Routine initially called when a non-boot CPU is brought online */
-static void __init start_secondary(void *unused)
-{
- __u8 cpuid = hard_smp_processor_id();
-
- cpu_init();
-
- /* OK, we're in the routine */
- ack_CPI(VIC_CPU_BOOT_CPI);
-
- /* setup the 8259 master slave pair belonging to this CPU ---
- * we won't actually receive any until the boot CPU
- * relinquishes it's static routing mask */
- vic_setup_pic();
-
- qic_setup();
-
- if (is_cpu_quad() && !is_cpu_vic_boot()) {
- /* clear the boot CPI */
- __u8 dummy;
-
- dummy =
- voyager_quad_cpi_addr[cpuid]->qic_cpi[VIC_CPU_BOOT_CPI].cpi;
- printk("read dummy %d\n", dummy);
- }
-
- /* lower the mask to receive CPIs */
- vic_enable_cpi();
-
- VDEBUG(("VOYAGER SMP: CPU%d, stack at about %p\n", cpuid, &cpuid));
-
- notify_cpu_starting(cpuid);
-
- /* enable interrupts */
- local_irq_enable();
-
- /* get our bogomips */
- calibrate_delay();
-
- /* save our processor parameters */
- smp_store_cpu_info(cpuid);
-
- /* if we're a quad, we may need to bootstrap other CPUs */
- do_quad_bootstrap();
-
- /* FIXME: this is rather a poor hack to prevent the CPU
- * activating softirqs while it's supposed to be waiting for
- * permission to proceed. Without this, the new per CPU stuff
- * in the softirqs will fail */
- local_irq_disable();
- cpu_set(cpuid, cpu_callin_map);
-
- /* signal that we're done */
- cpu_booted_map = 1;
-
- while (!cpu_isset(cpuid, smp_commenced_mask))
- rep_nop();
- local_irq_enable();
-
- local_flush_tlb();
-
- cpu_set(cpuid, cpu_online_map);
- wmb();
- cpu_idle();
-}
-
-/* Routine to kick start the given CPU and wait for it to report ready
- * (or timeout in startup). When this routine returns, the requested
- * CPU is either fully running and configured or known to be dead.
- *
- * We call this routine sequentially 1 CPU at a time, so no need for
- * locking */
-
-static void __init do_boot_cpu(__u8 cpu)
-{
- struct task_struct *idle;
- int timeout;
- unsigned long flags;
- int quad_boot = (1 << cpu) & voyager_quad_processors
- & ~(voyager_extended_vic_processors
- & voyager_allowed_boot_processors);
-
- /* This is the format of the CPI IDT gate (in real mode) which
- * we're hijacking to boot the CPU */
- union IDTFormat {
- struct seg {
- __u16 Offset;
- __u16 Segment;
- } idt;
- __u32 val;
- } hijack_source;
-
- __u32 *hijack_vector;
- __u32 start_phys_address = setup_trampoline();
-
- /* There's a clever trick to this: The linux trampoline is
- * compiled to begin at absolute location zero, so make the
- * address zero but have the data segment selector compensate
- * for the actual address */
- hijack_source.idt.Offset = start_phys_address & 0x000F;
- hijack_source.idt.Segment = (start_phys_address >> 4) & 0xFFFF;
-
- cpucount++;
- alternatives_smp_switch(1);
-
- idle = fork_idle(cpu);
- if (IS_ERR(idle))
- panic("failed fork for CPU%d", cpu);
- idle->thread.ip = (unsigned long)start_secondary;
- /* init_tasks (in sched.c) is indexed logically */
- stack_start.sp = (void *)idle->thread.sp;
-
- per_cpu(current_task, cpu) = idle;
- early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
- irq_ctx_init(cpu);
-
- /* Note: Don't modify initial ss override */
- VDEBUG(("VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p\n", cpu,
- (unsigned long)hijack_source.val, hijack_source.idt.Segment,
- hijack_source.idt.Offset, stack_start.sp));
-
- /* init lowmem identity mapping */
- clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY,
- min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
- flush_tlb_all();
-
- if (quad_boot) {
- printk("CPU %d: non extended Quad boot\n", cpu);
- hijack_vector =
- (__u32 *)
- phys_to_virt((VIC_CPU_BOOT_CPI + QIC_DEFAULT_CPI_BASE) * 4);
- *hijack_vector = hijack_source.val;
- } else {
- printk("CPU%d: extended VIC boot\n", cpu);
- hijack_vector =
- (__u32 *)
- phys_to_virt((VIC_CPU_BOOT_CPI + VIC_DEFAULT_CPI_BASE) * 4);
- *hijack_vector = hijack_source.val;
- /* VIC errata, may also receive interrupt at this address */
- hijack_vector =
- (__u32 *)
- phys_to_virt((VIC_CPU_BOOT_ERRATA_CPI +
- VIC_DEFAULT_CPI_BASE) * 4);
- *hijack_vector = hijack_source.val;
- }
- /* All non-boot CPUs start with interrupts fully masked. Need
- * to lower the mask of the CPI we're about to send. We do
- * this in the VIC by masquerading as the processor we're
- * about to boot and lowering its interrupt mask */
- local_irq_save(flags);
- if (quad_boot) {
- send_one_QIC_CPI(cpu, VIC_CPU_BOOT_CPI);
- } else {
- outb(VIC_CPU_MASQUERADE_ENABLE | cpu, VIC_PROCESSOR_ID);
- /* here we're altering registers belonging to `cpu' */
-
- outb(VIC_BOOT_INTERRUPT_MASK, 0x21);
- /* now go back to our original identity */
- outb(boot_cpu_id, VIC_PROCESSOR_ID);
-
- /* and boot the CPU */
-
- send_CPI((1 << cpu), VIC_CPU_BOOT_CPI);
- }
- cpu_booted_map = 0;
- local_irq_restore(flags);
-
- /* now wait for it to become ready (or timeout) */
- for (timeout = 0; timeout < 50000; timeout++) {
- if (cpu_booted_map)
- break;
- udelay(100);
- }
- /* reset the page table */
- zap_low_mappings();
-
- if (cpu_booted_map) {
- VDEBUG(("CPU%d: Booted successfully, back in CPU %d\n",
- cpu, smp_processor_id()));
-
- printk("CPU%d: ", cpu);
- print_cpu_info(&cpu_data(cpu));
- wmb();
- cpu_set(cpu, cpu_callout_map);
- cpu_set(cpu, cpu_present_map);
- } else {
- printk("CPU%d FAILED TO BOOT: ", cpu);
- if (*
- ((volatile unsigned char *)phys_to_virt(start_phys_address))
- == 0xA5)
- printk("Stuck.\n");
- else
- printk("Not responding.\n");
-
- cpucount--;
- }
-}
-
-void __init smp_boot_cpus(void)
-{
- int i;
-
- /* CAT BUS initialisation must be done after the memory */
- /* FIXME: The L4 has a catbus too, it just needs to be
- * accessed in a totally different way */
- if (voyager_level == 5) {
- voyager_cat_init();
-
- /* now that the cat has probed the Voyager System Bus, sanity
- * check the cpu map */
- if (((voyager_quad_processors | voyager_extended_vic_processors)
- & cpus_addr(phys_cpu_present_map)[0]) !=
- cpus_addr(phys_cpu_present_map)[0]) {
- /* should panic */
- printk("\n\n***WARNING*** "
- "Sanity check of CPU present map FAILED\n");
- }
- } else if (voyager_level == 4)
- voyager_extended_vic_processors =
- cpus_addr(phys_cpu_present_map)[0];
-
- /* this sets up the idle task to run on the current cpu */
- voyager_extended_cpus = 1;
- /* Remove the global_irq_holder setting, it triggers a BUG() on
- * schedule at the moment */
- //global_irq_holder = boot_cpu_id;
-
- /* FIXME: Need to do something about this but currently only works
- * on CPUs with a tsc which none of mine have.
- smp_tune_scheduling();
- */
- smp_store_cpu_info(boot_cpu_id);
- /* setup the jump vector */
- initial_code = (unsigned long)initialize_secondary;
- printk("CPU%d: ", boot_cpu_id);
- print_cpu_info(&cpu_data(boot_cpu_id));
-
- if (is_cpu_quad()) {
- /* booting on a Quad CPU */
- printk("VOYAGER SMP: Boot CPU is Quad\n");
- qic_setup();
- do_quad_bootstrap();
- }
-
- /* enable our own CPIs */
- vic_enable_cpi();
-
- cpu_set(boot_cpu_id, cpu_online_map);
- cpu_set(boot_cpu_id, cpu_callout_map);
-
- /* loop over all the extended VIC CPUs and boot them. The
- * Quad CPUs must be bootstrapped by their extended VIC cpu */
- for (i = 0; i < nr_cpu_ids; i++) {
- if (i == boot_cpu_id || !cpu_isset(i, phys_cpu_present_map))
- continue;
- do_boot_cpu(i);
- /* This udelay seems to be needed for the Quad boots
- * don't remove unless you know what you're doing */
- udelay(1000);
- }
- /* we could compute the total bogomips here, but why bother?,
- * Code added from smpboot.c */
- {
- unsigned long bogosum = 0;
-
- for_each_online_cpu(i)
- bogosum += cpu_data(i).loops_per_jiffy;
- printk(KERN_INFO "Total of %d processors activated "
- "(%lu.%02lu BogoMIPS).\n",
- cpucount + 1, bogosum / (500000 / HZ),
- (bogosum / (5000 / HZ)) % 100);
- }
- voyager_extended_cpus = hweight32(voyager_extended_vic_processors);
- printk("VOYAGER: Extended (interrupt handling CPUs): "
- "%d, non-extended: %d\n", voyager_extended_cpus,
- num_booting_cpus() - voyager_extended_cpus);
- /* that's it, switch to symmetric mode */
- outb(0, VIC_PRIORITY_REGISTER);
- outb(0, VIC_CLAIM_REGISTER_0);
- outb(0, VIC_CLAIM_REGISTER_1);
-
- VDEBUG(("VOYAGER SMP: Booted with %d CPUs\n", num_booting_cpus()));
-}
-
-/* Reload the secondary CPUs task structure (this function does not
- * return ) */
-static void __init initialize_secondary(void)
-{
-#if 0
- // AC kernels only
- set_current(hard_get_current());
-#endif
-
- /*
- * We don't actually need to load the full TSS,
- * basically just the stack pointer and the eip.
- */
-
- asm volatile ("movl %0,%%esp\n\t"
- "jmp *%1"::"r" (current->thread.sp),
- "r"(current->thread.ip));
-}
-
-/* handle a Voyager SYS_INT -- If we don't, the base board will
- * panic the system.
- *
- * System interrupts occur because some problem was detected on the
- * various busses. To find out what you have to probe all the
- * hardware via the CAT bus. FIXME: At the moment we do nothing. */
-void smp_vic_sys_interrupt(struct pt_regs *regs)
-{
- ack_CPI(VIC_SYS_INT);
- printk("Voyager SYSTEM INTERRUPT\n");
-}
-
-/* Handle a voyager CMN_INT; These interrupts occur either because of
- * a system status change or because a single bit memory error
- * occurred. FIXME: At the moment, ignore all this. */
-void smp_vic_cmn_interrupt(struct pt_regs *regs)
-{
- static __u8 in_cmn_int = 0;
- static DEFINE_SPINLOCK(cmn_int_lock);
-
- /* common ints are broadcast, so make sure we only do this once */
- _raw_spin_lock(&cmn_int_lock);
- if (in_cmn_int)
- goto unlock_end;
-
- in_cmn_int++;
- _raw_spin_unlock(&cmn_int_lock);
-
- VDEBUG(("Voyager COMMON INTERRUPT\n"));
-
- if (voyager_level == 5)
- voyager_cat_do_common_interrupt();
-
- _raw_spin_lock(&cmn_int_lock);
- in_cmn_int = 0;
- unlock_end:
- _raw_spin_unlock(&cmn_int_lock);
- ack_CPI(VIC_CMN_INT);
-}
-
-/*
- * Reschedule call back. Nothing to do, all the work is done
- * automatically when we return from the interrupt. */
-static void smp_reschedule_interrupt(void)
-{
- /* do nothing */
-}
-
-static struct mm_struct *flush_mm;
-static unsigned long flush_va;
-static DEFINE_SPINLOCK(tlbstate_lock);
-
-/*
- * We cannot call mmdrop() because we are in interrupt context,
- * instead update mm->cpu_vm_mask.
- *
- * We need to reload %cr3 since the page tables may be going
- * away from under us..
- */
-static inline void voyager_leave_mm(unsigned long cpu)
-{
- if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK)
- BUG();
- cpu_clear(cpu, per_cpu(cpu_tlbstate, cpu).active_mm->cpu_vm_mask);
- load_cr3(swapper_pg_dir);
-}
-
-/*
- * Invalidate call-back
- */
-static void smp_invalidate_interrupt(void)
-{
- __u8 cpu = smp_processor_id();
-
- if (!test_bit(cpu, &smp_invalidate_needed))
- return;
- /* This will flood messages. Don't uncomment unless you see
- * Problems with cross cpu invalidation
- VDEBUG(("VOYAGER SMP: CPU%d received INVALIDATE_CPI\n",
- smp_processor_id()));
- */
-
- if (flush_mm == per_cpu(cpu_tlbstate, cpu).active_mm) {
- if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_OK) {
- if (flush_va == TLB_FLUSH_ALL)
- local_flush_tlb();
- else
- __flush_tlb_one(flush_va);
- } else
- voyager_leave_mm(cpu);
- }
- smp_mb__before_clear_bit();
- clear_bit(cpu, &smp_invalidate_needed);
- smp_mb__after_clear_bit();
-}
-
-/* All the new flush operations for 2.4 */
-
-/* This routine is called with a physical cpu mask */
-static void
-voyager_flush_tlb_others(unsigned long cpumask, struct mm_struct *mm,
- unsigned long va)
-{
- int stuck = 50000;
-
- if (!cpumask)
- BUG();
- if ((cpumask & cpus_addr(cpu_online_map)[0]) != cpumask)
- BUG();
- if (cpumask & (1 << smp_processor_id()))
- BUG();
- if (!mm)
- BUG();
-
- spin_lock(&tlbstate_lock);
-
- flush_mm = mm;
- flush_va = va;
- atomic_set_mask(cpumask, &smp_invalidate_needed);
- /*
- * We have to send the CPI only to
- * CPUs affected.
- */
- send_CPI(cpumask, VIC_INVALIDATE_CPI);
-
- while (smp_invalidate_needed) {
- mb();
- if (--stuck == 0) {
- printk("***WARNING*** Stuck doing invalidate CPI "
- "(CPU%d)\n", smp_processor_id());
- break;
- }
- }
-
- /* Uncomment only to debug invalidation problems
- VDEBUG(("VOYAGER SMP: Completed invalidate CPI (CPU%d)\n", cpu));
- */
-
- flush_mm = NULL;
- flush_va = 0;
- spin_unlock(&tlbstate_lock);
-}
-
-void flush_tlb_current_task(void)
-{
- struct mm_struct *mm = current->mm;
- unsigned long cpu_mask;
-
- preempt_disable();
-
- cpu_mask = cpus_addr(mm->cpu_vm_mask)[0] & ~(1 << smp_processor_id());
- local_flush_tlb();
- if (cpu_mask)
- voyager_flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
-
- preempt_enable();
-}
-
-void flush_tlb_mm(struct mm_struct *mm)
-{
- unsigned long cpu_mask;
-
- preempt_disable();
-
- cpu_mask = cpus_addr(mm->cpu_vm_mask)[0] & ~(1 << smp_processor_id());
-
- if (current->active_mm == mm) {
- if (current->mm)
- local_flush_tlb();
- else
- voyager_leave_mm(smp_processor_id());
- }
- if (cpu_mask)
- voyager_flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL);
-
- preempt_enable();
-}
-
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
-{
- struct mm_struct *mm = vma->vm_mm;
- unsigned long cpu_mask;
-
- preempt_disable();
-
- cpu_mask = cpus_addr(mm->cpu_vm_mask)[0] & ~(1 << smp_processor_id());
- if (current->active_mm == mm) {
- if (current->mm)
- __flush_tlb_one(va);
- else
- voyager_leave_mm(smp_processor_id());
- }
-
- if (cpu_mask)
- voyager_flush_tlb_others(cpu_mask, mm, va);
-
- preempt_enable();
-}
-
-EXPORT_SYMBOL(flush_tlb_page);
-
-/* enable the requested IRQs */
-static void smp_enable_irq_interrupt(void)
-{
- __u8 irq;
- __u8 cpu = get_cpu();
-
- VDEBUG(("VOYAGER SMP: CPU%d enabling irq mask 0x%x\n", cpu,
- vic_irq_enable_mask[cpu]));
-
- spin_lock(&vic_irq_lock);
- for (irq = 0; irq < 16; irq++) {
- if (vic_irq_enable_mask[cpu] & (1 << irq))
- enable_local_vic_irq(irq);
- }
- vic_irq_enable_mask[cpu] = 0;
- spin_unlock(&vic_irq_lock);
-
- put_cpu_no_resched();
-}
-
-/*
- * CPU halt call-back
- */
-static void smp_stop_cpu_function(void *dummy)
-{
- VDEBUG(("VOYAGER SMP: CPU%d is STOPPING\n", smp_processor_id()));
- cpu_clear(smp_processor_id(), cpu_online_map);
- local_irq_disable();
- for (;;)
- halt();
-}
-
-/* execute a thread on a new CPU. The function to be called must be
- * previously set up. This is used to schedule a function for
- * execution on all CPUs - set up the function then broadcast a
- * function_interrupt CPI to come here on each CPU */
-static void smp_call_function_interrupt(void)
-{
- irq_enter();
- generic_smp_call_function_interrupt();
- __get_cpu_var(irq_stat).irq_call_count++;
- irq_exit();
-}
-
-static void smp_call_function_single_interrupt(void)
-{
- irq_enter();
- generic_smp_call_function_single_interrupt();
- __get_cpu_var(irq_stat).irq_call_count++;
- irq_exit();
-}
-
-/* Sorry about the name. In an APIC based system, the APICs
- * themselves are programmed to send a timer interrupt. This is used
- * by linux to reschedule the processor. Voyager doesn't have this,
- * so we use the system clock to interrupt one processor, which in
- * turn, broadcasts a timer CPI to all the others --- we receive that
- * CPI here. We don't use this actually for counting so losing
- * ticks doesn't matter
- *
- * FIXME: For those CPUs which actually have a local APIC, we could
- * try to use it to trigger this interrupt instead of having to
- * broadcast the timer tick. Unfortunately, all my pentium DYADs have
- * no local APIC, so I can't do this
- *
- * This function is currently a placeholder and is unused in the code */
-void smp_apic_timer_interrupt(struct pt_regs *regs)
-{
- struct pt_regs *old_regs = set_irq_regs(regs);
- wrapper_smp_local_timer_interrupt();
- set_irq_regs(old_regs);
-}
-
-/* All of the QUAD interrupt GATES */
-void smp_qic_timer_interrupt(struct pt_regs *regs)
-{
- struct pt_regs *old_regs = set_irq_regs(regs);
- ack_QIC_CPI(QIC_TIMER_CPI);
- wrapper_smp_local_timer_interrupt();
- set_irq_regs(old_regs);
-}
-
-void smp_qic_invalidate_interrupt(struct pt_regs *regs)
-{
- ack_QIC_CPI(QIC_INVALIDATE_CPI);
- smp_invalidate_interrupt();
-}
-
-void smp_qic_reschedule_interrupt(struct pt_regs *regs)
-{
- ack_QIC_CPI(QIC_RESCHEDULE_CPI);
- smp_reschedule_interrupt();
-}
-
-void smp_qic_enable_irq_interrupt(struct pt_regs *regs)
-{
- ack_QIC_CPI(QIC_ENABLE_IRQ_CPI);
- smp_enable_irq_interrupt();
-}
-
-void smp_qic_call_function_interrupt(struct pt_regs *regs)
-{
- ack_QIC_CPI(QIC_CALL_FUNCTION_CPI);
- smp_call_function_interrupt();
-}
-
-void smp_qic_call_function_single_interrupt(struct pt_regs *regs)
-{
- ack_QIC_CPI(QIC_CALL_FUNCTION_SINGLE_CPI);
- smp_call_function_single_interrupt();
-}
-
-void smp_vic_cpi_interrupt(struct pt_regs *regs)
-{
- struct pt_regs *old_regs = set_irq_regs(regs);
- __u8 cpu = smp_processor_id();
-
- if (is_cpu_quad())
- ack_QIC_CPI(VIC_CPI_LEVEL0);
- else
- ack_VIC_CPI(VIC_CPI_LEVEL0);
-
- if (test_and_clear_bit(VIC_TIMER_CPI, &vic_cpi_mailbox[cpu]))
- wrapper_smp_local_timer_interrupt();
- if (test_and_clear_bit(VIC_INVALIDATE_CPI, &vic_cpi_mailbox[cpu]))
- smp_invalidate_interrupt();
- if (test_and_clear_bit(VIC_RESCHEDULE_CPI, &vic_cpi_mailbox[cpu]))
- smp_reschedule_interrupt();
- if (test_and_clear_bit(VIC_ENABLE_IRQ_CPI, &vic_cpi_mailbox[cpu]))
- smp_enable_irq_interrupt();
- if (test_and_clear_bit(VIC_CALL_FUNCTION_CPI, &vic_cpi_mailbox[cpu]))
- smp_call_function_interrupt();
- if (test_and_clear_bit(VIC_CALL_FUNCTION_SINGLE_CPI, &vic_cpi_mailbox[cpu]))
- smp_call_function_single_interrupt();
- set_irq_regs(old_regs);
-}
-
-static void do_flush_tlb_all(void *info)
-{
- unsigned long cpu = smp_processor_id();
-
- __flush_tlb_all();
- if (per_cpu(cpu_tlbstate, cpu).state == TLBSTATE_LAZY)
- voyager_leave_mm(cpu);
-}
-
-/* flush the TLB of every active CPU in the system */
-void flush_tlb_all(void)
-{
- on_each_cpu(do_flush_tlb_all, 0, 1);
-}
-
-/* send a reschedule CPI to one CPU by physical CPU number*/
-static void voyager_smp_send_reschedule(int cpu)
-{
- send_one_CPI(cpu, VIC_RESCHEDULE_CPI);
-}
-
-int hard_smp_processor_id(void)
-{
- __u8 i;
- __u8 cpumask = inb(VIC_PROC_WHO_AM_I);
- if ((cpumask & QUAD_IDENTIFIER) == QUAD_IDENTIFIER)
- return cpumask & 0x1F;
-
- for (i = 0; i < 8; i++) {
- if (cpumask & (1 << i))
- return i;
- }
- printk("** WARNING ** Illegal cpuid returned by VIC: %d", cpumask);
- return 0;
-}
-
-int safe_smp_processor_id(void)
-{
- return hard_smp_processor_id();
-}
-
-/* broadcast a halt to all other CPUs */
-static void voyager_smp_send_stop(void)
-{
- smp_call_function(smp_stop_cpu_function, NULL, 1);
-}
-
-/* this function is triggered in time.c when a clock tick fires
- * we need to re-broadcast the tick to all CPUs */
-void smp_vic_timer_interrupt(void)
-{
- send_CPI_allbutself(VIC_TIMER_CPI);
- smp_local_timer_interrupt();
-}
-
-/* local (per CPU) timer interrupt. It does both profiling and
- * process statistics/rescheduling.
- *
- * We do profiling in every local tick, statistics/rescheduling
- * happen only every 'profiling multiplier' ticks. The default
- * multiplier is 1 and it can be changed by writing the new multiplier
- * value into /proc/profile.
- */
-void smp_local_timer_interrupt(void)
-{
- int cpu = smp_processor_id();
- long weight;
-
- profile_tick(CPU_PROFILING);
- if (--per_cpu(prof_counter, cpu) <= 0) {
- /*
- * The multiplier may have changed since the last time we got
- * to this point as a result of the user writing to
- * /proc/profile. In this case we need to adjust the APIC
- * timer accordingly.
- *
- * Interrupts are already masked off at this point.
- */
- per_cpu(prof_counter, cpu) = per_cpu(prof_multiplier, cpu);
- if (per_cpu(prof_counter, cpu) !=
- per_cpu(prof_old_multiplier, cpu)) {
- /* FIXME: need to update the vic timer tick here */
- per_cpu(prof_old_multiplier, cpu) =
- per_cpu(prof_counter, cpu);
- }
-
- update_process_times(user_mode_vm(get_irq_regs()));
- }
-
- if (((1 << cpu) & voyager_extended_vic_processors) == 0)
- /* only extended VIC processors participate in
- * interrupt distribution */
- return;
-
- /*
- * We take the 'long' return path, and there every subsystem
- * grabs the appropriate locks (kernel lock/ irq lock).
- *
- * we might want to decouple profiling from the 'long path',
- * and do the profiling totally in assembly.
- *
- * Currently this isn't too much of an issue (performance wise),
- * we can take more than 100K local irqs per second on a 100 MHz P5.
- */
-
- if ((++vic_tick[cpu] & 0x7) != 0)
- return;
- /* get here every 16 ticks (about every 1/6 of a second) */
-
- /* Change our priority to give someone else a chance at getting
- * the IRQ. The algorithm goes like this:
- *
- * In the VIC, the dynamically routed interrupt is always
- * handled by the lowest priority eligible (i.e. receiving
- * interrupts) CPU. If >1 eligible CPUs are equal lowest, the
- * lowest processor number gets it.
- *
- * The priority of a CPU is controlled by a special per-CPU
- * VIC priority register which is 3 bits wide 0 being lowest
- * and 7 highest priority..
- *
- * Therefore we subtract the average number of interrupts from
- * the number we've fielded. If this number is negative, we
- * lower the activity count and if it is positive, we raise
- * it.
- *
- * I'm afraid this still leads to odd looking interrupt counts:
- * the totals are all roughly equal, but the individual ones
- * look rather skewed.
- *
- * FIXME: This algorithm is total crap when mixed with SMP
- * affinity code since we now try to even up the interrupt
- * counts when an affinity binding is keeping them on a
- * particular CPU*/
- weight = (vic_intr_count[cpu] * voyager_extended_cpus
- - vic_intr_total) >> 4;
- weight += 4;
- if (weight > 7)
- weight = 7;
- if (weight < 0)
- weight = 0;
-
- outb((__u8) weight, VIC_PRIORITY_REGISTER);
-
-#ifdef VOYAGER_DEBUG
- if ((vic_tick[cpu] & 0xFFF) == 0) {
- /* print this message roughly every 25 secs */
- printk("VOYAGER SMP: vic_tick[%d] = %lu, weight = %ld\n",
- cpu, vic_tick[cpu], weight);
- }
-#endif
-}
-
-/* setup the profiling timer */
-int setup_profiling_timer(unsigned int multiplier)
-{
- int i;
-
- if ((!multiplier))
- return -EINVAL;
-
- /*
- * Set the new multiplier for each CPU. CPUs don't start using the
- * new values until the next timer interrupt in which they do process
- * accounting.
- */
- for (i = 0; i < nr_cpu_ids; ++i)
- per_cpu(prof_multiplier, i) = multiplier;
-
- return 0;
-}
-
-/* This is a bit of a mess, but forced on us by the genirq changes
- * there's no genirq handler that really does what voyager wants
- * so hack it up with the simple IRQ handler */
-static void handle_vic_irq(unsigned int irq, struct irq_desc *desc)
-{
- before_handle_vic_irq(irq);
- handle_simple_irq(irq, desc);
- after_handle_vic_irq(irq);
-}
-
-/* The CPIs are handled in the per cpu 8259s, so they must be
- * enabled to be received: FIX: enabling the CPIs in the early
- * boot sequence interferes with bug checking; enable them later
- * on in smp_init */
-#define VIC_SET_GATE(cpi, vector) \
- set_intr_gate((cpi) + VIC_DEFAULT_CPI_BASE, (vector))
-#define QIC_SET_GATE(cpi, vector) \
- set_intr_gate((cpi) + QIC_DEFAULT_CPI_BASE, (vector))
-
-void __init voyager_smp_intr_init(void)
-{
- int i;
-
- /* initialize the per cpu irq mask to all disabled */
- for (i = 0; i < nr_cpu_ids; i++)
- vic_irq_mask[i] = 0xFFFF;
-
- VIC_SET_GATE(VIC_CPI_LEVEL0, vic_cpi_interrupt);
-
- VIC_SET_GATE(VIC_SYS_INT, vic_sys_interrupt);
- VIC_SET_GATE(VIC_CMN_INT, vic_cmn_interrupt);
-
- QIC_SET_GATE(QIC_TIMER_CPI, qic_timer_interrupt);
- QIC_SET_GATE(QIC_INVALIDATE_CPI, qic_invalidate_interrupt);
- QIC_SET_GATE(QIC_RESCHEDULE_CPI, qic_reschedule_interrupt);
- QIC_SET_GATE(QIC_ENABLE_IRQ_CPI, qic_enable_irq_interrupt);
- QIC_SET_GATE(QIC_CALL_FUNCTION_CPI, qic_call_function_interrupt);
-
- /* now put the VIC descriptor into the first 48 IRQs
- *
- * This is for later: first 16 correspond to PC IRQs; next 16
- * are Primary MC IRQs and final 16 are Secondary MC IRQs */
- for (i = 0; i < 48; i++)
- set_irq_chip_and_handler(i, &vic_chip, handle_vic_irq);
-}
-
-/* send a CPI at level cpi to a set of cpus in cpuset (set 1 bit per
- * processor to receive CPI */
-static void send_CPI(__u32 cpuset, __u8 cpi)
-{
- int cpu;
- __u32 quad_cpuset = (cpuset & voyager_quad_processors);
-
- if (cpi < VIC_START_FAKE_CPI) {
- /* fake CPI are only used for booting, so send to the
- * extended quads as well---Quads must be VIC booted */
- outb((__u8) (cpuset), VIC_CPI_Registers[cpi]);
- return;
- }
- if (quad_cpuset)
- send_QIC_CPI(quad_cpuset, cpi);
- cpuset &= ~quad_cpuset;
- cpuset &= 0xff; /* only first 8 CPUs vaild for VIC CPI */
- if (cpuset == 0)
- return;
- for_each_online_cpu(cpu) {
- if (cpuset & (1 << cpu))
- set_bit(cpi, &vic_cpi_mailbox[cpu]);
- }
- if (cpuset)
- outb((__u8) cpuset, VIC_CPI_Registers[VIC_CPI_LEVEL0]);
-}
-
-/* Acknowledge receipt of CPI in the QIC, clear in QIC hardware and
- * set the cache line to shared by reading it.
- *
- * DON'T make this inline otherwise the cache line read will be
- * optimised away
- * */
-static int ack_QIC_CPI(__u8 cpi)
-{
- __u8 cpu = hard_smp_processor_id();
-
- cpi &= 7;
-
- outb(1 << cpi, QIC_INTERRUPT_CLEAR1);
- return voyager_quad_cpi_addr[cpu]->qic_cpi[cpi].cpi;
-}
-
-static void ack_special_QIC_CPI(__u8 cpi)
-{
- switch (cpi) {
- case VIC_CMN_INT:
- outb(QIC_CMN_INT, QIC_INTERRUPT_CLEAR0);
- break;
- case VIC_SYS_INT:
- outb(QIC_SYS_INT, QIC_INTERRUPT_CLEAR0);
- break;
- }
- /* also clear at the VIC, just in case (nop for non-extended proc) */
- ack_VIC_CPI(cpi);
-}
-
-/* Acknowledge receipt of CPI in the VIC (essentially an EOI) */
-static void ack_VIC_CPI(__u8 cpi)
-{
-#ifdef VOYAGER_DEBUG
- unsigned long flags;
- __u16 isr;
- __u8 cpu = smp_processor_id();
-
- local_irq_save(flags);
- isr = vic_read_isr();
- if ((isr & (1 << (cpi & 7))) == 0) {
- printk("VOYAGER SMP: CPU%d lost CPI%d\n", cpu, cpi);
- }
-#endif
- /* send specific EOI; the two system interrupts have
- * bit 4 set for a separate vector but behave as the
- * corresponding 3 bit intr */
- outb_p(0x60 | (cpi & 7), 0x20);
-
-#ifdef VOYAGER_DEBUG
- if ((vic_read_isr() & (1 << (cpi & 7))) != 0) {
- printk("VOYAGER SMP: CPU%d still asserting CPI%d\n", cpu, cpi);
- }
- local_irq_restore(flags);
-#endif
-}
-
-/* cribbed with thanks from irq.c */
-#define __byte(x,y) (((unsigned char *)&(y))[x])
-#define cached_21(cpu) (__byte(0,vic_irq_mask[cpu]))
-#define cached_A1(cpu) (__byte(1,vic_irq_mask[cpu]))
-
-static unsigned int startup_vic_irq(unsigned int irq)
-{
- unmask_vic_irq(irq);
-
- return 0;
-}
-
-/* The enable and disable routines. This is where we run into
- * conflicting architectural philosophy. Fundamentally, the voyager
- * architecture does not expect to have to disable interrupts globally
- * (the IRQ controllers belong to each CPU). The processor masquerade
- * which is used to start the system shouldn't be used in a running OS
- * since it will cause great confusion if two separate CPUs drive to
- * the same IRQ controller (I know, I've tried it).
- *
- * The solution is a variant on the NCR lazy SPL design:
- *
- * 1) To disable an interrupt, do nothing (other than set the
- * IRQ_DISABLED flag). This dares the interrupt actually to arrive.
- *
- * 2) If the interrupt dares to come in, raise the local mask against
- * it (this will result in all the CPU masks being raised
- * eventually).
- *
- * 3) To enable the interrupt, lower the mask on the local CPU and
- * broadcast an Interrupt enable CPI which causes all other CPUs to
- * adjust their masks accordingly. */
-
-static void unmask_vic_irq(unsigned int irq)
-{
- /* linux doesn't to processor-irq affinity, so enable on
- * all CPUs we know about */
- int cpu = smp_processor_id(), real_cpu;
- __u16 mask = (1 << irq);
- __u32 processorList = 0;
- unsigned long flags;
-
- VDEBUG(("VOYAGER: unmask_vic_irq(%d) CPU%d affinity 0x%lx\n",
- irq, cpu, cpu_irq_affinity[cpu]));
- spin_lock_irqsave(&vic_irq_lock, flags);
- for_each_online_cpu(real_cpu) {
- if (!(voyager_extended_vic_processors & (1 << real_cpu)))
- continue;
- if (!(cpu_irq_affinity[real_cpu] & mask)) {
- /* irq has no affinity for this CPU, ignore */
- continue;
- }
- if (real_cpu == cpu) {
- enable_local_vic_irq(irq);
- } else if (vic_irq_mask[real_cpu] & mask) {
- vic_irq_enable_mask[real_cpu] |= mask;
- processorList |= (1 << real_cpu);
- }
- }
- spin_unlock_irqrestore(&vic_irq_lock, flags);
- if (processorList)
- send_CPI(processorList, VIC_ENABLE_IRQ_CPI);
-}
-
-static void mask_vic_irq(unsigned int irq)
-{
- /* lazy disable, do nothing */
-}
-
-static void enable_local_vic_irq(unsigned int irq)
-{
- __u8 cpu = smp_processor_id();
- __u16 mask = ~(1 << irq);
- __u16 old_mask = vic_irq_mask[cpu];
-
- vic_irq_mask[cpu] &= mask;
- if (vic_irq_mask[cpu] == old_mask)
- return;
-
- VDEBUG(("VOYAGER DEBUG: Enabling irq %d in hardware on CPU %d\n",
- irq, cpu));
-
- if (irq & 8) {
- outb_p(cached_A1(cpu), 0xA1);
- (void)inb_p(0xA1);
- } else {
- outb_p(cached_21(cpu), 0x21);
- (void)inb_p(0x21);
- }
-}
-
-static void disable_local_vic_irq(unsigned int irq)
-{
- __u8 cpu = smp_processor_id();
- __u16 mask = (1 << irq);
- __u16 old_mask = vic_irq_mask[cpu];
-
- if (irq == 7)
- return;
-
- vic_irq_mask[cpu] |= mask;
- if (old_mask == vic_irq_mask[cpu])
- return;
-
- VDEBUG(("VOYAGER DEBUG: Disabling irq %d in hardware on CPU %d\n",
- irq, cpu));
-
- if (irq & 8) {
- outb_p(cached_A1(cpu), 0xA1);
- (void)inb_p(0xA1);
- } else {
- outb_p(cached_21(cpu), 0x21);
- (void)inb_p(0x21);
- }
-}
-
-/* The VIC is level triggered, so the ack can only be issued after the
- * interrupt completes. However, we do Voyager lazy interrupt
- * handling here: It is an extremely expensive operation to mask an
- * interrupt in the vic, so we merely set a flag (IRQ_DISABLED). If
- * this interrupt actually comes in, then we mask and ack here to push
- * the interrupt off to another CPU */
-static void before_handle_vic_irq(unsigned int irq)
-{
- irq_desc_t *desc = irq_to_desc(irq);
- __u8 cpu = smp_processor_id();
-
- _raw_spin_lock(&vic_irq_lock);
- vic_intr_total++;
- vic_intr_count[cpu]++;
-
- if (!(cpu_irq_affinity[cpu] & (1 << irq))) {
- /* The irq is not in our affinity mask, push it off
- * onto another CPU */
- VDEBUG(("VOYAGER DEBUG: affinity triggered disable of irq %d "
- "on cpu %d\n", irq, cpu));
- disable_local_vic_irq(irq);
- /* set IRQ_INPROGRESS to prevent the handler in irq.c from
- * actually calling the interrupt routine */
- desc->status |= IRQ_REPLAY | IRQ_INPROGRESS;
- } else if (desc->status & IRQ_DISABLED) {
- /* Damn, the interrupt actually arrived, do the lazy
- * disable thing. The interrupt routine in irq.c will
- * not handle a IRQ_DISABLED interrupt, so nothing more
- * need be done here */
- VDEBUG(("VOYAGER DEBUG: lazy disable of irq %d on CPU %d\n",
- irq, cpu));
- disable_local_vic_irq(irq);
- desc->status |= IRQ_REPLAY;
- } else {
- desc->status &= ~IRQ_REPLAY;
- }
-
- _raw_spin_unlock(&vic_irq_lock);
-}
-
-/* Finish the VIC interrupt: basically mask */
-static void after_handle_vic_irq(unsigned int irq)
-{
- irq_desc_t *desc = irq_to_desc(irq);
-
- _raw_spin_lock(&vic_irq_lock);
- {
- unsigned int status = desc->status & ~IRQ_INPROGRESS;
-#ifdef VOYAGER_DEBUG
- __u16 isr;
-#endif
-
- desc->status = status;
- if ((status & IRQ_DISABLED))
- disable_local_vic_irq(irq);
-#ifdef VOYAGER_DEBUG
- /* DEBUG: before we ack, check what's in progress */
- isr = vic_read_isr();
- if ((isr & (1 << irq) && !(status & IRQ_REPLAY)) == 0) {
- int i;
- __u8 cpu = smp_processor_id();
- __u8 real_cpu;
- int mask; /* Um... initialize me??? --RR */
-
- printk("VOYAGER SMP: CPU%d lost interrupt %d\n",
- cpu, irq);
- for_each_possible_cpu(real_cpu, mask) {
-
- outb(VIC_CPU_MASQUERADE_ENABLE | real_cpu,
- VIC_PROCESSOR_ID);
- isr = vic_read_isr();
- if (isr & (1 << irq)) {
- printk
- ("VOYAGER SMP: CPU%d ack irq %d\n",
- real_cpu, irq);
- ack_vic_irq(irq);
- }
- outb(cpu, VIC_PROCESSOR_ID);
- }
- }
-#endif /* VOYAGER_DEBUG */
- /* as soon as we ack, the interrupt is eligible for
- * receipt by another CPU so everything must be in
- * order here */
- ack_vic_irq(irq);
- if (status & IRQ_REPLAY) {
- /* replay is set if we disable the interrupt
- * in the before_handle_vic_irq() routine, so
- * clear the in progress bit here to allow the
- * next CPU to handle this correctly */
- desc->status &= ~(IRQ_REPLAY | IRQ_INPROGRESS);
- }
-#ifdef VOYAGER_DEBUG
- isr = vic_read_isr();
- if ((isr & (1 << irq)) != 0)
- printk("VOYAGER SMP: after_handle_vic_irq() after "
- "ack irq=%d, isr=0x%x\n", irq, isr);
-#endif /* VOYAGER_DEBUG */
- }
- _raw_spin_unlock(&vic_irq_lock);
-
- /* All code after this point is out of the main path - the IRQ
- * may be intercepted by another CPU if reasserted */
-}
-
-/* Linux processor - interrupt affinity manipulations.
- *
- * For each processor, we maintain a 32 bit irq affinity mask.
- * Initially it is set to all 1's so every processor accepts every
- * interrupt. In this call, we change the processor's affinity mask:
- *
- * Change from enable to disable:
- *
- * If the interrupt ever comes in to the processor, we will disable it
- * and ack it to push it off to another CPU, so just accept the mask here.
- *
- * Change from disable to enable:
- *
- * change the mask and then do an interrupt enable CPI to re-enable on
- * the selected processors */
-
-void set_vic_irq_affinity(unsigned int irq, const struct cpumask *mask)
-{
- /* Only extended processors handle interrupts */
- unsigned long real_mask;
- unsigned long irq_mask = 1 << irq;
- int cpu;
-
- real_mask = cpus_addr(*mask)[0] & voyager_extended_vic_processors;
-
- if (cpus_addr(*mask)[0] == 0)
- /* can't have no CPUs to accept the interrupt -- extremely
- * bad things will happen */
- return;
-
- if (irq == 0)
- /* can't change the affinity of the timer IRQ. This
- * is due to the constraint in the voyager
- * architecture that the CPI also comes in on and IRQ
- * line and we have chosen IRQ0 for this. If you
- * raise the mask on this interrupt, the processor
- * will no-longer be able to accept VIC CPIs */
- return;
-
- if (irq >= 32)
- /* You can only have 32 interrupts in a voyager system
- * (and 32 only if you have a secondary microchannel
- * bus) */
- return;
-
- for_each_online_cpu(cpu) {
- unsigned long cpu_mask = 1 << cpu;
-
- if (cpu_mask & real_mask) {
- /* enable the interrupt for this cpu */
- cpu_irq_affinity[cpu] |= irq_mask;
- } else {
- /* disable the interrupt for this cpu */
- cpu_irq_affinity[cpu] &= ~irq_mask;
- }
- }
- /* this is magic, we now have the correct affinity maps, so
- * enable the interrupt. This will send an enable CPI to
- * those CPUs who need to enable it in their local masks,
- * causing them to correct for the new affinity . If the
- * interrupt is currently globally disabled, it will simply be
- * disabled again as it comes in (voyager lazy disable). If
- * the affinity map is tightened to disable the interrupt on a
- * cpu, it will be pushed off when it comes in */
- unmask_vic_irq(irq);
-}
-
-static void ack_vic_irq(unsigned int irq)
-{
- if (irq & 8) {
- outb(0x62, 0x20); /* Specific EOI to cascade */
- outb(0x60 | (irq & 7), 0xA0);
- } else {
- outb(0x60 | (irq & 7), 0x20);
- }
-}
-
-/* enable the CPIs. In the VIC, the CPIs are delivered by the 8259
- * but are not vectored by it. This means that the 8259 mask must be
- * lowered to receive them */
-static __init void vic_enable_cpi(void)
-{
- __u8 cpu = smp_processor_id();
-
- /* just take a copy of the current mask (nop for boot cpu) */
- vic_irq_mask[cpu] = vic_irq_mask[boot_cpu_id];
-
- enable_local_vic_irq(VIC_CPI_LEVEL0);
- enable_local_vic_irq(VIC_CPI_LEVEL1);
- /* for sys int and cmn int */
- enable_local_vic_irq(7);
-
- if (is_cpu_quad()) {
- outb(QIC_DEFAULT_MASK0, QIC_MASK_REGISTER0);
- outb(QIC_CPI_ENABLE, QIC_MASK_REGISTER1);
- VDEBUG(("VOYAGER SMP: QIC ENABLE CPI: CPU%d: MASK 0x%x\n",
- cpu, QIC_CPI_ENABLE));
- }
-
- VDEBUG(("VOYAGER SMP: ENABLE CPI: CPU%d: MASK 0x%x\n",
- cpu, vic_irq_mask[cpu]));
-}
-
-void voyager_smp_dump()
-{
- int old_cpu = smp_processor_id(), cpu;
-
- /* dump the interrupt masks of each processor */
- for_each_online_cpu(cpu) {
- __u16 imr, isr, irr;
- unsigned long flags;
-
- local_irq_save(flags);
- outb(VIC_CPU_MASQUERADE_ENABLE | cpu, VIC_PROCESSOR_ID);
- imr = (inb(0xa1) << 8) | inb(0x21);
- outb(0x0a, 0xa0);
- irr = inb(0xa0) << 8;
- outb(0x0a, 0x20);
- irr |= inb(0x20);
- outb(0x0b, 0xa0);
- isr = inb(0xa0) << 8;
- outb(0x0b, 0x20);
- isr |= inb(0x20);
- outb(old_cpu, VIC_PROCESSOR_ID);
- local_irq_restore(flags);
- printk("\tCPU%d: mask=0x%x, IMR=0x%x, IRR=0x%x, ISR=0x%x\n",
- cpu, vic_irq_mask[cpu], imr, irr, isr);
-#if 0
- /* These lines are put in to try to unstick an un ack'd irq */
- if (isr != 0) {
- int irq;
- for (irq = 0; irq < 16; irq++) {
- if (isr & (1 << irq)) {
- printk("\tCPU%d: ack irq %d\n",
- cpu, irq);
- local_irq_save(flags);
- outb(VIC_CPU_MASQUERADE_ENABLE | cpu,
- VIC_PROCESSOR_ID);
- ack_vic_irq(irq);
- outb(old_cpu, VIC_PROCESSOR_ID);
- local_irq_restore(flags);
- }
- }
- }
-#endif
- }
-}
-
-void smp_voyager_power_off(void *dummy)
-{
- if (smp_processor_id() == boot_cpu_id)
- voyager_power_off();
- else
- smp_stop_cpu_function(NULL);
-}
-
-static void __init voyager_smp_prepare_cpus(unsigned int max_cpus)
-{
- /* FIXME: ignore max_cpus for now */
- smp_boot_cpus();
-}
-
-static void __cpuinit voyager_smp_prepare_boot_cpu(void)
-{
- int cpu = smp_processor_id();
- switch_to_new_gdt(cpu);
-
- cpu_set(cpu, cpu_online_map);
- cpu_set(cpu, cpu_callout_map);
- cpu_set(cpu, cpu_possible_map);
- cpu_set(cpu, cpu_present_map);
-
-}
-
-static int __cpuinit voyager_cpu_up(unsigned int cpu)
-{
- /* This only works at boot for x86. See "rewrite" above. */
- if (cpu_isset(cpu, smp_commenced_mask))
- return -ENOSYS;
-
- /* In case one didn't come up */
- if (!cpu_isset(cpu, cpu_callin_map))
- return -EIO;
- /* Unleash the CPU! */
- cpu_set(cpu, smp_commenced_mask);
- while (!cpu_online(cpu))
- mb();
- return 0;
-}
-
-static void __init voyager_smp_cpus_done(unsigned int max_cpus)
-{
- zap_low_mappings();
-}
-
-void __init smp_setup_processor_id(void)
-{
- current_thread_info()->cpu = hard_smp_processor_id();
-}
-
-static void voyager_send_call_func(const struct cpumask *callmask)
-{
- __u32 mask = cpus_addr(*callmask)[0] & ~(1 << smp_processor_id());
- send_CPI(mask, VIC_CALL_FUNCTION_CPI);
-}
-
-static void voyager_send_call_func_single(int cpu)
-{
- send_CPI(1 << cpu, VIC_CALL_FUNCTION_SINGLE_CPI);
-}
-
-struct smp_ops smp_ops = {
- .smp_prepare_boot_cpu = voyager_smp_prepare_boot_cpu,
- .smp_prepare_cpus = voyager_smp_prepare_cpus,
- .cpu_up = voyager_cpu_up,
- .smp_cpus_done = voyager_smp_cpus_done,
-
- .smp_send_stop = voyager_smp_send_stop,
- .smp_send_reschedule = voyager_smp_send_reschedule,
-
- .send_call_func_ipi = voyager_send_call_func,
- .send_call_func_single_ipi = voyager_send_call_func_single,
-};
diff --git a/arch/x86/mach-voyager/voyager_thread.c b/arch/x86/mach-voyager/voyager_thread.c
deleted file mode 100644
index 15464a20fb38..000000000000
--- a/arch/x86/mach-voyager/voyager_thread.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/* -*- mode: c; c-basic-offset: 8 -*- */
-
-/* Copyright (C) 2001
- *
- * Author: J.E.J.Bottomley@HansenPartnership.com
- *
- * This module provides the machine status monitor thread for the
- * voyager architecture. This allows us to monitor the machine
- * environment (temp, voltage, fan function) and the front panel and
- * internal UPS. If a fault is detected, this thread takes corrective
- * action (usually just informing init)
- * */
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#include <linux/mc146818rtc.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/kmod.h>
-#include <linux/completion.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <asm/desc.h>
-#include <asm/voyager.h>
-#include <asm/vic.h>
-#include <asm/mtrr.h>
-#include <asm/msr.h>
-
-struct task_struct *voyager_thread;
-static __u8 set_timeout;
-
-static int execute(const char *string)
-{
- int ret;
-
- char *envp[] = {
- "HOME=/",
- "TERM=linux",
- "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
- NULL,
- };
- char *argv[] = {
- "/bin/bash",
- "-c",
- (char *)string,
- NULL,
- };
-
- if ((ret =
- call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC)) != 0) {
- printk(KERN_ERR "Voyager failed to run \"%s\": %i\n", string,
- ret);
- }
- return ret;
-}
-
-static void check_from_kernel(void)
-{
- if (voyager_status.switch_off) {
-
- /* FIXME: This should be configurable via proc */
- execute("umask 600; echo 0 > /etc/initrunlvl; kill -HUP 1");
- } else if (voyager_status.power_fail) {
- VDEBUG(("Voyager daemon detected AC power failure\n"));
-
- /* FIXME: This should be configureable via proc */
- execute("umask 600; echo F > /etc/powerstatus; kill -PWR 1");
- set_timeout = 1;
- }
-}
-
-static void check_continuing_condition(void)
-{
- if (voyager_status.power_fail) {
- __u8 data;
- voyager_cat_psi(VOYAGER_PSI_SUBREAD,
- VOYAGER_PSI_AC_FAIL_REG, &data);
- if ((data & 0x1f) == 0) {
- /* all power restored */
- printk(KERN_NOTICE
- "VOYAGER AC power restored, cancelling shutdown\n");
- /* FIXME: should be user configureable */
- execute
- ("umask 600; echo O > /etc/powerstatus; kill -PWR 1");
- set_timeout = 0;
- }
- }
-}
-
-static int thread(void *unused)
-{
- printk(KERN_NOTICE "Voyager starting monitor thread\n");
-
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(set_timeout ? HZ : MAX_SCHEDULE_TIMEOUT);
-
- VDEBUG(("Voyager Daemon awoken\n"));
- if (voyager_status.request_from_kernel == 0) {
- /* probably awoken from timeout */
- check_continuing_condition();
- } else {
- check_from_kernel();
- voyager_status.request_from_kernel = 0;
- }
- }
-}
-
-static int __init voyager_thread_start(void)
-{
- voyager_thread = kthread_run(thread, NULL, "kvoyagerd");
- if (IS_ERR(voyager_thread)) {
- printk(KERN_ERR
- "Voyager: Failed to create system monitor thread.\n");
- return PTR_ERR(voyager_thread);
- }
- return 0;
-}
-
-static void __exit voyager_thread_stop(void)
-{
- kthread_stop(voyager_thread);
-}
-
-module_init(voyager_thread_start);
-module_exit(voyager_thread_stop);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 29644175490f..a03b7279efa0 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1,74 +1,79 @@
/*
* Copyright (C) 1995 Linus Torvalds
- * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs.
+ * Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
+ * Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
*/
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mmiotrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/vt_kern.h> /* For unblank_screen() */
+#include <linux/mmiotrace.h>
+#include <linux/bootmem.h>
#include <linux/compiler.h>
#include <linux/highmem.h>
-#include <linux/bootmem.h> /* for max_low_pfn */
-#include <linux/vmalloc.h>
-#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+#include <linux/vt_kern.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/module.h>
#include <linux/kdebug.h>
+#include <linux/errno.h>
#include <linux/magic.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/mman.h>
+#include <linux/tty.h>
+#include <linux/smp.h>
+#include <linux/mm.h>
+
+#include <asm-generic/sections.h>
-#include <asm/system.h>
-#include <asm/desc.h>
-#include <asm/segment.h>
-#include <asm/pgalloc.h>
-#include <asm/smp.h>
#include <asm/tlbflush.h>
+#include <asm/pgalloc.h>
+#include <asm/segment.h>
+#include <asm/system.h>
#include <asm/proto.h>
-#include <asm-generic/sections.h>
#include <asm/traps.h>
+#include <asm/desc.h>
/*
- * Page fault error code bits
- * bit 0 == 0 means no page found, 1 means protection fault
- * bit 1 == 0 means read, 1 means write
- * bit 2 == 0 means kernel, 1 means user-mode
- * bit 3 == 1 means use of reserved bit detected
- * bit 4 == 1 means fault was an instruction fetch
+ * Page fault error code bits:
+ *
+ * bit 0 == 0: no page found 1: protection fault
+ * bit 1 == 0: read access 1: write access
+ * bit 2 == 0: kernel-mode access 1: user-mode access
+ * bit 3 == 1: use of reserved bit detected
+ * bit 4 == 1: fault was an instruction fetch
*/
-#define PF_PROT (1<<0)
-#define PF_WRITE (1<<1)
-#define PF_USER (1<<2)
-#define PF_RSVD (1<<3)
-#define PF_INSTR (1<<4)
+enum x86_pf_error_code {
+ PF_PROT = 1 << 0,
+ PF_WRITE = 1 << 1,
+ PF_USER = 1 << 2,
+ PF_RSVD = 1 << 3,
+ PF_INSTR = 1 << 4,
+};
+
+/*
+ * Returns 0 if mmiotrace is disabled, or if the fault is not
+ * handled by mmiotrace:
+ */
static inline int kmmio_fault(struct pt_regs *regs, unsigned long addr)
{
-#ifdef CONFIG_MMIOTRACE
if (unlikely(is_kmmio_active()))
if (kmmio_handler(regs, addr) == 1)
return -1;
-#endif
return 0;
}
static inline int notify_page_fault(struct pt_regs *regs)
{
-#ifdef CONFIG_KPROBES
int ret = 0;
/* kprobe_running() needs smp_processor_id() */
- if (!user_mode_vm(regs)) {
+ if (kprobes_built_in() && !user_mode_vm(regs)) {
preempt_disable();
if (kprobe_running() && kprobe_fault_handler(regs, 14))
ret = 1;
@@ -76,29 +81,76 @@ static inline int notify_page_fault(struct pt_regs *regs)
}
return ret;
-#else
- return 0;
-#endif
}
/*
- * X86_32
- * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
- * Check that here and ignore it.
+ * Prefetch quirks:
*
- * X86_64
- * Sometimes the CPU reports invalid exceptions on prefetch.
- * Check that here and ignore it.
+ * 32-bit mode:
*
- * Opcode checker based on code by Richard Brunner
+ * Sometimes AMD Athlon/Opteron CPUs report invalid exceptions on prefetch.
+ * Check that here and ignore it.
+ *
+ * 64-bit mode:
+ *
+ * Sometimes the CPU reports invalid exceptions on prefetch.
+ * Check that here and ignore it.
+ *
+ * Opcode checker based on code by Richard Brunner.
*/
-static int is_prefetch(struct pt_regs *regs, unsigned long error_code,
- unsigned long addr)
+static inline int
+check_prefetch_opcode(struct pt_regs *regs, unsigned char *instr,
+ unsigned char opcode, int *prefetch)
{
+ unsigned char instr_hi = opcode & 0xf0;
+ unsigned char instr_lo = opcode & 0x0f;
+
+ switch (instr_hi) {
+ case 0x20:
+ case 0x30:
+ /*
+ * Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes.
+ * In X86_64 long mode, the CPU will signal invalid
+ * opcode if some of these prefixes are present so
+ * X86_64 will never get here anyway
+ */
+ return ((instr_lo & 7) == 0x6);
+#ifdef CONFIG_X86_64
+ case 0x40:
+ /*
+ * In AMD64 long mode 0x40..0x4F are valid REX prefixes
+ * Need to figure out under what instruction mode the
+ * instruction was issued. Could check the LDT for lm,
+ * but for now it's good enough to assume that long
+ * mode only uses well known segments or kernel.
+ */
+ return (!user_mode(regs)) || (regs->cs == __USER_CS);
+#endif
+ case 0x60:
+ /* 0x64 thru 0x67 are valid prefixes in all modes. */
+ return (instr_lo & 0xC) == 0x4;
+ case 0xF0:
+ /* 0xF0, 0xF2, 0xF3 are valid prefixes in all modes. */
+ return !instr_lo || (instr_lo>>1) == 1;
+ case 0x00:
+ /* Prefetch instruction is 0x0F0D or 0x0F18 */
+ if (probe_kernel_address(instr, opcode))
+ return 0;
+
+ *prefetch = (instr_lo == 0xF) &&
+ (opcode == 0x0D || opcode == 0x18);
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static int
+is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
+{
+ unsigned char *max_instr;
unsigned char *instr;
- int scan_more = 1;
int prefetch = 0;
- unsigned char *max_instr;
/*
* If it was a exec (instruction fetch) fault on NX page, then
@@ -107,106 +159,170 @@ static int is_prefetch(struct pt_regs *regs, unsigned long error_code,
if (error_code & PF_INSTR)
return 0;
- instr = (unsigned char *)convert_ip_to_linear(current, regs);
+ instr = (void *)convert_ip_to_linear(current, regs);
max_instr = instr + 15;
if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
return 0;
- while (scan_more && instr < max_instr) {
+ while (instr < max_instr) {
unsigned char opcode;
- unsigned char instr_hi;
- unsigned char instr_lo;
if (probe_kernel_address(instr, opcode))
break;
- instr_hi = opcode & 0xf0;
- instr_lo = opcode & 0x0f;
instr++;
- switch (instr_hi) {
- case 0x20:
- case 0x30:
- /*
- * Values 0x26,0x2E,0x36,0x3E are valid x86 prefixes.
- * In X86_64 long mode, the CPU will signal invalid
- * opcode if some of these prefixes are present so
- * X86_64 will never get here anyway
- */
- scan_more = ((instr_lo & 7) == 0x6);
- break;
-#ifdef CONFIG_X86_64
- case 0x40:
- /*
- * In AMD64 long mode 0x40..0x4F are valid REX prefixes
- * Need to figure out under what instruction mode the
- * instruction was issued. Could check the LDT for lm,
- * but for now it's good enough to assume that long
- * mode only uses well known segments or kernel.
- */
- scan_more = (!user_mode(regs)) || (regs->cs == __USER_CS);
- break;
-#endif
- case 0x60:
- /* 0x64 thru 0x67 are valid prefixes in all modes. */
- scan_more = (instr_lo & 0xC) == 0x4;
- break;
- case 0xF0:
- /* 0xF0, 0xF2, 0xF3 are valid prefixes in all modes. */
- scan_more = !instr_lo || (instr_lo>>1) == 1;
- break;
- case 0x00:
- /* Prefetch instruction is 0x0F0D or 0x0F18 */
- scan_more = 0;
-
- if (probe_kernel_address(instr, opcode))
- break;
- prefetch = (instr_lo == 0xF) &&
- (opcode == 0x0D || opcode == 0x18);
+ if (!check_prefetch_opcode(regs, instr, opcode, &prefetch))
break;
- default:
- scan_more = 0;
- break;
- }
}
return prefetch;
}
-static void force_sig_info_fault(int si_signo, int si_code,
- unsigned long address, struct task_struct *tsk)
+static void
+force_sig_info_fault(int si_signo, int si_code, unsigned long address,
+ struct task_struct *tsk)
{
siginfo_t info;
- info.si_signo = si_signo;
- info.si_errno = 0;
- info.si_code = si_code;
- info.si_addr = (void __user *)address;
+ info.si_signo = si_signo;
+ info.si_errno = 0;
+ info.si_code = si_code;
+ info.si_addr = (void __user *)address;
+
force_sig_info(si_signo, &info, tsk);
}
-#ifdef CONFIG_X86_64
-static int bad_address(void *p)
+DEFINE_SPINLOCK(pgd_lock);
+LIST_HEAD(pgd_list);
+
+#ifdef CONFIG_X86_32
+static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
{
- unsigned long dummy;
- return probe_kernel_address((unsigned long *)p, dummy);
+ unsigned index = pgd_index(address);
+ pgd_t *pgd_k;
+ pud_t *pud, *pud_k;
+ pmd_t *pmd, *pmd_k;
+
+ pgd += index;
+ pgd_k = init_mm.pgd + index;
+
+ if (!pgd_present(*pgd_k))
+ return NULL;
+
+ /*
+ * set_pgd(pgd, *pgd_k); here would be useless on PAE
+ * and redundant with the set_pmd() on non-PAE. As would
+ * set_pud.
+ */
+ pud = pud_offset(pgd, address);
+ pud_k = pud_offset(pgd_k, address);
+ if (!pud_present(*pud_k))
+ return NULL;
+
+ pmd = pmd_offset(pud, address);
+ pmd_k = pmd_offset(pud_k, address);
+ if (!pmd_present(*pmd_k))
+ return NULL;
+
+ if (!pmd_present(*pmd)) {
+ set_pmd(pmd, *pmd_k);
+ arch_flush_lazy_mmu_mode();
+ } else {
+ BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
+ }
+
+ return pmd_k;
+}
+
+void vmalloc_sync_all(void)
+{
+ unsigned long address;
+
+ if (SHARED_KERNEL_PMD)
+ return;
+
+ for (address = VMALLOC_START & PMD_MASK;
+ address >= TASK_SIZE && address < FIXADDR_TOP;
+ address += PMD_SIZE) {
+
+ unsigned long flags;
+ struct page *page;
+
+ spin_lock_irqsave(&pgd_lock, flags);
+ list_for_each_entry(page, &pgd_list, lru) {
+ if (!vmalloc_sync_one(page_address(page), address))
+ break;
+ }
+ spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+}
+
+/*
+ * 32-bit:
+ *
+ * Handle a fault on the vmalloc or module mapping area
+ */
+static noinline int vmalloc_fault(unsigned long address)
+{
+ unsigned long pgd_paddr;
+ pmd_t *pmd_k;
+ pte_t *pte_k;
+
+ /* Make sure we are in vmalloc area: */
+ if (!(address >= VMALLOC_START && address < VMALLOC_END))
+ return -1;
+
+ /*
+ * Synchronize this task's top level page-table
+ * with the 'reference' page table.
+ *
+ * Do _not_ use "current" here. We might be inside
+ * an interrupt in the middle of a task switch..
+ */
+ pgd_paddr = read_cr3();
+ pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
+ if (!pmd_k)
+ return -1;
+
+ pte_k = pte_offset_kernel(pmd_k, address);
+ if (!pte_present(*pte_k))
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Did it hit the DOS screen memory VA from vm86 mode?
+ */
+static inline void
+check_v8086_mode(struct pt_regs *regs, unsigned long address,
+ struct task_struct *tsk)
+{
+ unsigned long bit;
+
+ if (!v8086_mode(regs))
+ return;
+
+ bit = (address - 0xA0000) >> PAGE_SHIFT;
+ if (bit < 32)
+ tsk->thread.screen_bitmap |= 1 << bit;
}
-#endif
static void dump_pagetable(unsigned long address)
{
-#ifdef CONFIG_X86_32
__typeof__(pte_val(__pte(0))) page;
page = read_cr3();
page = ((__typeof__(page) *) __va(page))[address >> PGDIR_SHIFT];
+
#ifdef CONFIG_X86_PAE
printk("*pdpt = %016Lx ", page);
if ((page >> PAGE_SHIFT) < max_low_pfn
&& page & _PAGE_PRESENT) {
page &= PAGE_MASK;
page = ((__typeof__(page) *) __va(page))[(address >> PMD_SHIFT)
- & (PTRS_PER_PMD - 1)];
+ & (PTRS_PER_PMD - 1)];
printk(KERN_CONT "*pde = %016Lx ", page);
page &= ~_PAGE_NX;
}
@@ -218,19 +334,145 @@ static void dump_pagetable(unsigned long address)
* We must not directly access the pte in the highpte
* case if the page table is located in highmem.
* And let's rather not kmap-atomic the pte, just in case
- * it's allocated already.
+ * it's allocated already:
*/
if ((page >> PAGE_SHIFT) < max_low_pfn
&& (page & _PAGE_PRESENT)
&& !(page & _PAGE_PSE)) {
+
page &= PAGE_MASK;
page = ((__typeof__(page) *) __va(page))[(address >> PAGE_SHIFT)
- & (PTRS_PER_PTE - 1)];
+ & (PTRS_PER_PTE - 1)];
printk("*pte = %0*Lx ", sizeof(page)*2, (u64)page);
}
printk("\n");
-#else /* CONFIG_X86_64 */
+}
+
+#else /* CONFIG_X86_64: */
+
+void vmalloc_sync_all(void)
+{
+ unsigned long address;
+
+ for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
+ address += PGDIR_SIZE) {
+
+ const pgd_t *pgd_ref = pgd_offset_k(address);
+ unsigned long flags;
+ struct page *page;
+
+ if (pgd_none(*pgd_ref))
+ continue;
+
+ spin_lock_irqsave(&pgd_lock, flags);
+ list_for_each_entry(page, &pgd_list, lru) {
+ pgd_t *pgd;
+ pgd = (pgd_t *)page_address(page) + pgd_index(address);
+ if (pgd_none(*pgd))
+ set_pgd(pgd, *pgd_ref);
+ else
+ BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+ }
+ spin_unlock_irqrestore(&pgd_lock, flags);
+ }
+}
+
+/*
+ * 64-bit:
+ *
+ * Handle a fault on the vmalloc area
+ *
+ * This assumes no large pages in there.
+ */
+static noinline int vmalloc_fault(unsigned long address)
+{
+ pgd_t *pgd, *pgd_ref;
+ pud_t *pud, *pud_ref;
+ pmd_t *pmd, *pmd_ref;
+ pte_t *pte, *pte_ref;
+
+ /* Make sure we are in vmalloc area: */
+ if (!(address >= VMALLOC_START && address < VMALLOC_END))
+ return -1;
+
+ /*
+ * Copy kernel mappings over when needed. This can also
+ * happen within a race in page table update. In the later
+ * case just flush:
+ */
+ pgd = pgd_offset(current->active_mm, address);
+ pgd_ref = pgd_offset_k(address);
+ if (pgd_none(*pgd_ref))
+ return -1;
+
+ if (pgd_none(*pgd))
+ set_pgd(pgd, *pgd_ref);
+ else
+ BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
+
+ /*
+ * Below here mismatches are bugs because these lower tables
+ * are shared:
+ */
+
+ pud = pud_offset(pgd, address);
+ pud_ref = pud_offset(pgd_ref, address);
+ if (pud_none(*pud_ref))
+ return -1;
+
+ if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
+ BUG();
+
+ pmd = pmd_offset(pud, address);
+ pmd_ref = pmd_offset(pud_ref, address);
+ if (pmd_none(*pmd_ref))
+ return -1;
+
+ if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
+ BUG();
+
+ pte_ref = pte_offset_kernel(pmd_ref, address);
+ if (!pte_present(*pte_ref))
+ return -1;
+
+ pte = pte_offset_kernel(pmd, address);
+
+ /*
+ * Don't use pte_page here, because the mappings can point
+ * outside mem_map, and the NUMA hash lookup cannot handle
+ * that:
+ */
+ if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
+ BUG();
+
+ return 0;
+}
+
+static const char errata93_warning[] =
+KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
+KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
+KERN_ERR "******* Please consider a BIOS update.\n"
+KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
+
+/*
+ * No vm86 mode in 64-bit mode:
+ */
+static inline void
+check_v8086_mode(struct pt_regs *regs, unsigned long address,
+ struct task_struct *tsk)
+{
+}
+
+static int bad_address(void *p)
+{
+ unsigned long dummy;
+
+ return probe_kernel_address((unsigned long *)p, dummy);
+}
+
+static void dump_pagetable(unsigned long address)
+{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
@@ -239,102 +481,77 @@ static void dump_pagetable(unsigned long address)
pgd = (pgd_t *)read_cr3();
pgd = __va((unsigned long)pgd & PHYSICAL_PAGE_MASK);
+
pgd += pgd_index(address);
- if (bad_address(pgd)) goto bad;
+ if (bad_address(pgd))
+ goto bad;
+
printk("PGD %lx ", pgd_val(*pgd));
- if (!pgd_present(*pgd)) goto ret;
+
+ if (!pgd_present(*pgd))
+ goto out;
pud = pud_offset(pgd, address);
- if (bad_address(pud)) goto bad;
+ if (bad_address(pud))
+ goto bad;
+
printk("PUD %lx ", pud_val(*pud));
if (!pud_present(*pud) || pud_large(*pud))
- goto ret;
+ goto out;
pmd = pmd_offset(pud, address);
- if (bad_address(pmd)) goto bad;
+ if (bad_address(pmd))
+ goto bad;
+
printk("PMD %lx ", pmd_val(*pmd));
- if (!pmd_present(*pmd) || pmd_large(*pmd)) goto ret;
+ if (!pmd_present(*pmd) || pmd_large(*pmd))
+ goto out;
pte = pte_offset_kernel(pmd, address);
- if (bad_address(pte)) goto bad;
+ if (bad_address(pte))
+ goto bad;
+
printk("PTE %lx", pte_val(*pte));
-ret:
+out:
printk("\n");
return;
bad:
printk("BAD\n");
-#endif
}
-#ifdef CONFIG_X86_32
-static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
-{
- unsigned index = pgd_index(address);
- pgd_t *pgd_k;
- pud_t *pud, *pud_k;
- pmd_t *pmd, *pmd_k;
-
- pgd += index;
- pgd_k = init_mm.pgd + index;
-
- if (!pgd_present(*pgd_k))
- return NULL;
+#endif /* CONFIG_X86_64 */
- /*
- * set_pgd(pgd, *pgd_k); here would be useless on PAE
- * and redundant with the set_pmd() on non-PAE. As would
- * set_pud.
- */
-
- pud = pud_offset(pgd, address);
- pud_k = pud_offset(pgd_k, address);
- if (!pud_present(*pud_k))
- return NULL;
-
- pmd = pmd_offset(pud, address);
- pmd_k = pmd_offset(pud_k, address);
- if (!pmd_present(*pmd_k))
- return NULL;
- if (!pmd_present(*pmd)) {
- set_pmd(pmd, *pmd_k);
- arch_flush_lazy_mmu_mode();
- } else
- BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
- return pmd_k;
-}
-#endif
-
-#ifdef CONFIG_X86_64
-static const char errata93_warning[] =
-KERN_ERR "******* Your BIOS seems to not contain a fix for K8 errata #93\n"
-KERN_ERR "******* Working around it, but it may cause SEGVs or burn power.\n"
-KERN_ERR "******* Please consider a BIOS update.\n"
-KERN_ERR "******* Disabling USB legacy in the BIOS may also help.\n";
-#endif
-
-/* Workaround for K8 erratum #93 & buggy BIOS.
- BIOS SMM functions are required to use a specific workaround
- to avoid corruption of the 64bit RIP register on C stepping K8.
- A lot of BIOS that didn't get tested properly miss this.
- The OS sees this as a page fault with the upper 32bits of RIP cleared.
- Try to work around it here.
- Note we only handle faults in kernel here.
- Does nothing for X86_32
+/*
+ * Workaround for K8 erratum #93 & buggy BIOS.
+ *
+ * BIOS SMM functions are required to use a specific workaround
+ * to avoid corruption of the 64bit RIP register on C stepping K8.
+ *
+ * A lot of BIOS that didn't get tested properly miss this.
+ *
+ * The OS sees this as a page fault with the upper 32bits of RIP cleared.
+ * Try to work around it here.
+ *
+ * Note we only handle faults in kernel here.
+ * Does nothing on 32-bit.
*/
static int is_errata93(struct pt_regs *regs, unsigned long address)
{
#ifdef CONFIG_X86_64
- static int warned;
+ static int once;
+
if (address != regs->ip)
return 0;
+
if ((address >> 32) != 0)
return 0;
+
address |= 0xffffffffUL << 32;
if ((address >= (u64)_stext && address <= (u64)_etext) ||
(address >= MODULES_VADDR && address <= MODULES_END)) {
- if (!warned) {
+ if (!once) {
printk(errata93_warning);
- warned = 1;
+ once = 1;
}
regs->ip = address;
return 1;
@@ -344,16 +561,17 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
}
/*
- * Work around K8 erratum #100 K8 in compat mode occasionally jumps to illegal
- * addresses >4GB. We catch this in the page fault handler because these
- * addresses are not reachable. Just detect this case and return. Any code
+ * Work around K8 erratum #100 K8 in compat mode occasionally jumps
+ * to illegal addresses >4GB.
+ *
+ * We catch this in the page fault handler because these addresses
+ * are not reachable. Just detect this case and return. Any code
* segment in LDT is compatibility mode.
*/
static int is_errata100(struct pt_regs *regs, unsigned long address)
{
#ifdef CONFIG_X86_64
- if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) &&
- (address >> 32))
+ if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && (address >> 32))
return 1;
#endif
return 0;
@@ -363,8 +581,9 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
{
#ifdef CONFIG_X86_F00F_BUG
unsigned long nr;
+
/*
- * Pentium F0 0F C7 C8 bug workaround.
+ * Pentium F0 0F C7 C8 bug workaround:
*/
if (boot_cpu_data.f00f_bug) {
nr = (address - idt_descr.address) >> 3;
@@ -378,80 +597,87 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
return 0;
}
-static void show_fault_oops(struct pt_regs *regs, unsigned long error_code,
- unsigned long address)
+static const char nx_warning[] = KERN_CRIT
+"kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n";
+
+static void
+show_fault_oops(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
{
-#ifdef CONFIG_X86_32
if (!oops_may_print())
return;
-#endif
-#ifdef CONFIG_X86_PAE
if (error_code & PF_INSTR) {
unsigned int level;
+
pte_t *pte = lookup_address(address, &level);
if (pte && pte_present(*pte) && !pte_exec(*pte))
- printk(KERN_CRIT "kernel tried to execute "
- "NX-protected page - exploit attempt? "
- "(uid: %d)\n", current_uid());
+ printk(nx_warning, current_uid());
}
-#endif
printk(KERN_ALERT "BUG: unable to handle kernel ");
if (address < PAGE_SIZE)
printk(KERN_CONT "NULL pointer dereference");
else
printk(KERN_CONT "paging request");
+
printk(KERN_CONT " at %p\n", (void *) address);
printk(KERN_ALERT "IP:");
printk_address(regs->ip, 1);
+
dump_pagetable(address);
}
-#ifdef CONFIG_X86_64
-static noinline void pgtable_bad(struct pt_regs *regs,
- unsigned long error_code, unsigned long address)
+static noinline void
+pgtable_bad(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
{
- unsigned long flags = oops_begin();
- int sig = SIGKILL;
- struct task_struct *tsk = current;
+ struct task_struct *tsk;
+ unsigned long flags;
+ int sig;
+
+ flags = oops_begin();
+ tsk = current;
+ sig = SIGKILL;
printk(KERN_ALERT "%s: Corrupted page table at address %lx\n",
tsk->comm, address);
dump_pagetable(address);
- tsk->thread.cr2 = address;
- tsk->thread.trap_no = 14;
- tsk->thread.error_code = error_code;
+
+ tsk->thread.cr2 = address;
+ tsk->thread.trap_no = 14;
+ tsk->thread.error_code = error_code;
+
if (__die("Bad pagetable", regs, error_code))
sig = 0;
+
oops_end(flags, regs, sig);
}
-#endif
-static noinline void no_context(struct pt_regs *regs,
- unsigned long error_code, unsigned long address)
+static noinline void
+no_context(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
{
struct task_struct *tsk = current;
unsigned long *stackend;
-
-#ifdef CONFIG_X86_64
unsigned long flags;
int sig;
-#endif
- /* Are we prepared to handle this kernel fault? */
+ /* Are we prepared to handle this kernel fault? */
if (fixup_exception(regs))
return;
/*
- * X86_32
- * Valid to do another page fault here, because if this fault
- * had been triggered by is_prefetch fixup_exception would have
- * handled it.
+ * 32-bit:
+ *
+ * Valid to do another page fault here, because if this fault
+ * had been triggered by is_prefetch fixup_exception would have
+ * handled it.
+ *
+ * 64-bit:
*
- * X86_64
- * Hall of shame of CPU/BIOS bugs.
+ * Hall of shame of CPU/BIOS bugs.
*/
if (is_prefetch(regs, error_code, address))
return;
@@ -461,54 +687,70 @@ static noinline void no_context(struct pt_regs *regs,
/*
* Oops. The kernel tried to access some bad page. We'll have to
- * terminate things with extreme prejudice.
+ * terminate things with extreme prejudice:
*/
-#ifdef CONFIG_X86_32
- bust_spinlocks(1);
-#else
flags = oops_begin();
-#endif
show_fault_oops(regs, error_code, address);
- stackend = end_of_stack(tsk);
+ stackend = end_of_stack(tsk);
if (*stackend != STACK_END_MAGIC)
printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
- tsk->thread.cr2 = address;
- tsk->thread.trap_no = 14;
- tsk->thread.error_code = error_code;
+ tsk->thread.cr2 = address;
+ tsk->thread.trap_no = 14;
+ tsk->thread.error_code = error_code;
-#ifdef CONFIG_X86_32
- die("Oops", regs, error_code);
- bust_spinlocks(0);
- do_exit(SIGKILL);
-#else
sig = SIGKILL;
if (__die("Oops", regs, error_code))
sig = 0;
+
/* Executive summary in case the body of the oops scrolled away */
printk(KERN_EMERG "CR2: %016lx\n", address);
+
oops_end(flags, regs, sig);
-#endif
}
-static void __bad_area_nosemaphore(struct pt_regs *regs,
- unsigned long error_code, unsigned long address,
- int si_code)
+/*
+ * Print out info about fatal segfaults, if the show_unhandled_signals
+ * sysctl is set:
+ */
+static inline void
+show_signal_msg(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address, struct task_struct *tsk)
+{
+ if (!unhandled_signal(tsk, SIGSEGV))
+ return;
+
+ if (!printk_ratelimit())
+ return;
+
+ printk(KERN_CONT "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
+ task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
+ tsk->comm, task_pid_nr(tsk), address,
+ (void *)regs->ip, (void *)regs->sp, error_code);
+
+ print_vma_addr(KERN_CONT " in ", regs->ip);
+
+ printk(KERN_CONT "\n");
+}
+
+static void
+__bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address, int si_code)
{
struct task_struct *tsk = current;
/* User mode accesses just cause a SIGSEGV */
if (error_code & PF_USER) {
/*
- * It's possible to have interrupts off here.
+ * It's possible to have interrupts off here:
*/
local_irq_enable();
/*
* Valid to do another page fault here because this one came
- * from user space.
+ * from user space:
*/
if (is_prefetch(regs, error_code, address))
return;
@@ -516,22 +758,16 @@ static void __bad_area_nosemaphore(struct pt_regs *regs,
if (is_errata100(regs, address))
return;
- if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
- printk_ratelimit()) {
- printk(
- "%s%s[%d]: segfault at %lx ip %p sp %p error %lx",
- task_pid_nr(tsk) > 1 ? KERN_INFO : KERN_EMERG,
- tsk->comm, task_pid_nr(tsk), address,
- (void *) regs->ip, (void *) regs->sp, error_code);
- print_vma_addr(" in ", regs->ip);
- printk("\n");
- }
+ if (unlikely(show_unhandled_signals))
+ show_signal_msg(regs, error_code, address, tsk);
+
+ /* Kernel addresses are always protection faults: */
+ tsk->thread.cr2 = address;
+ tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+ tsk->thread.trap_no = 14;
- tsk->thread.cr2 = address;
- /* Kernel addresses are always protection faults */
- tsk->thread.error_code = error_code | (address >= TASK_SIZE);
- tsk->thread.trap_no = 14;
force_sig_info_fault(SIGSEGV, si_code, address, tsk);
+
return;
}
@@ -541,15 +777,16 @@ static void __bad_area_nosemaphore(struct pt_regs *regs,
no_context(regs, error_code, address);
}
-static noinline void bad_area_nosemaphore(struct pt_regs *regs,
- unsigned long error_code, unsigned long address)
+static noinline void
+bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
{
__bad_area_nosemaphore(regs, error_code, address, SEGV_MAPERR);
}
-static void __bad_area(struct pt_regs *regs,
- unsigned long error_code, unsigned long address,
- int si_code)
+static void
+__bad_area(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address, int si_code)
{
struct mm_struct *mm = current->mm;
@@ -562,67 +799,75 @@ static void __bad_area(struct pt_regs *regs,
__bad_area_nosemaphore(regs, error_code, address, si_code);
}
-static noinline void bad_area(struct pt_regs *regs,
- unsigned long error_code, unsigned long address)
+static noinline void
+bad_area(struct pt_regs *regs, unsigned long error_code, unsigned long address)
{
__bad_area(regs, error_code, address, SEGV_MAPERR);
}
-static noinline void bad_area_access_error(struct pt_regs *regs,
- unsigned long error_code, unsigned long address)
+static noinline void
+bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
{
__bad_area(regs, error_code, address, SEGV_ACCERR);
}
/* TODO: fixup for "mm-invoke-oom-killer-from-page-fault.patch" */
-static void out_of_memory(struct pt_regs *regs,
- unsigned long error_code, unsigned long address)
+static void
+out_of_memory(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address)
{
/*
* We ran out of memory, call the OOM killer, and return the userspace
- * (which will retry the fault, or kill us if we got oom-killed).
+ * (which will retry the fault, or kill us if we got oom-killed):
*/
up_read(&current->mm->mmap_sem);
+
pagefault_out_of_memory();
}
-static void do_sigbus(struct pt_regs *regs,
- unsigned long error_code, unsigned long address)
+static void
+do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address)
{
struct task_struct *tsk = current;
struct mm_struct *mm = tsk->mm;
up_read(&mm->mmap_sem);
- /* Kernel mode? Handle exceptions or die */
+ /* Kernel mode? Handle exceptions or die: */
if (!(error_code & PF_USER))
no_context(regs, error_code, address);
-#ifdef CONFIG_X86_32
- /* User space => ok to do another page fault */
+
+ /* User-space => ok to do another page fault: */
if (is_prefetch(regs, error_code, address))
return;
-#endif
- tsk->thread.cr2 = address;
- tsk->thread.error_code = error_code;
- tsk->thread.trap_no = 14;
+
+ tsk->thread.cr2 = address;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 14;
+
force_sig_info_fault(SIGBUS, BUS_ADRERR, address, tsk);
}
-static noinline void mm_fault_error(struct pt_regs *regs,
- unsigned long error_code, unsigned long address, unsigned int fault)
+static noinline void
+mm_fault_error(struct pt_regs *regs, unsigned long error_code,
+ unsigned long address, unsigned int fault)
{
- if (fault & VM_FAULT_OOM)
+ if (fault & VM_FAULT_OOM) {
out_of_memory(regs, error_code, address);
- else if (fault & VM_FAULT_SIGBUS)
- do_sigbus(regs, error_code, address);
- else
- BUG();
+ } else {
+ if (fault & VM_FAULT_SIGBUS)
+ do_sigbus(regs, error_code, address);
+ else
+ BUG();
+ }
}
static int spurious_fault_check(unsigned long error_code, pte_t *pte)
{
if ((error_code & PF_WRITE) && !pte_write(*pte))
return 0;
+
if ((error_code & PF_INSTR) && !pte_exec(*pte))
return 0;
@@ -630,21 +875,25 @@ static int spurious_fault_check(unsigned long error_code, pte_t *pte)
}
/*
- * Handle a spurious fault caused by a stale TLB entry. This allows
- * us to lazily refresh the TLB when increasing the permissions of a
- * kernel page (RO -> RW or NX -> X). Doing it eagerly is very
- * expensive since that implies doing a full cross-processor TLB
- * flush, even if no stale TLB entries exist on other processors.
+ * Handle a spurious fault caused by a stale TLB entry.
+ *
+ * This allows us to lazily refresh the TLB when increasing the
+ * permissions of a kernel page (RO -> RW or NX -> X). Doing it
+ * eagerly is very expensive since that implies doing a full
+ * cross-processor TLB flush, even if no stale TLB entries exist
+ * on other processors.
+ *
* There are no security implications to leaving a stale TLB when
* increasing the permissions on a page.
*/
-static noinline int spurious_fault(unsigned long error_code,
- unsigned long address)
+static noinline int
+spurious_fault(unsigned long error_code, unsigned long address)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
+ int ret;
/* Reserved-bit violation or user access to kernel space? */
if (error_code & (PF_USER | PF_RSVD))
@@ -672,123 +921,46 @@ static noinline int spurious_fault(unsigned long error_code,
if (!pte_present(*pte))
return 0;
- return spurious_fault_check(error_code, pte);
-}
-
-/*
- * X86_32
- * Handle a fault on the vmalloc or module mapping area
- *
- * X86_64
- * Handle a fault on the vmalloc area
- *
- * This assumes no large pages in there.
- */
-static noinline int vmalloc_fault(unsigned long address)
-{
-#ifdef CONFIG_X86_32
- unsigned long pgd_paddr;
- pmd_t *pmd_k;
- pte_t *pte_k;
-
- /* Make sure we are in vmalloc area */
- if (!(address >= VMALLOC_START && address < VMALLOC_END))
- return -1;
+ ret = spurious_fault_check(error_code, pte);
+ if (!ret)
+ return 0;
/*
- * Synchronize this task's top level page-table
- * with the 'reference' page table.
- *
- * Do _not_ use "current" here. We might be inside
- * an interrupt in the middle of a task switch..
+ * Make sure we have permissions in PMD.
+ * If not, then there's a bug in the page tables:
*/
- pgd_paddr = read_cr3();
- pmd_k = vmalloc_sync_one(__va(pgd_paddr), address);
- if (!pmd_k)
- return -1;
- pte_k = pte_offset_kernel(pmd_k, address);
- if (!pte_present(*pte_k))
- return -1;
- return 0;
-#else
- pgd_t *pgd, *pgd_ref;
- pud_t *pud, *pud_ref;
- pmd_t *pmd, *pmd_ref;
- pte_t *pte, *pte_ref;
+ ret = spurious_fault_check(error_code, (pte_t *) pmd);
+ WARN_ONCE(!ret, "PMD has incorrect permission bits\n");
- /* Make sure we are in vmalloc area */
- if (!(address >= VMALLOC_START && address < VMALLOC_END))
- return -1;
-
- /* Copy kernel mappings over when needed. This can also
- happen within a race in page table update. In the later
- case just flush. */
-
- pgd = pgd_offset(current->active_mm, address);
- pgd_ref = pgd_offset_k(address);
- if (pgd_none(*pgd_ref))
- return -1;
- if (pgd_none(*pgd))
- set_pgd(pgd, *pgd_ref);
- else
- BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
-
- /* Below here mismatches are bugs because these lower tables
- are shared */
-
- pud = pud_offset(pgd, address);
- pud_ref = pud_offset(pgd_ref, address);
- if (pud_none(*pud_ref))
- return -1;
- if (pud_none(*pud) || pud_page_vaddr(*pud) != pud_page_vaddr(*pud_ref))
- BUG();
- pmd = pmd_offset(pud, address);
- pmd_ref = pmd_offset(pud_ref, address);
- if (pmd_none(*pmd_ref))
- return -1;
- if (pmd_none(*pmd) || pmd_page(*pmd) != pmd_page(*pmd_ref))
- BUG();
- pte_ref = pte_offset_kernel(pmd_ref, address);
- if (!pte_present(*pte_ref))
- return -1;
- pte = pte_offset_kernel(pmd, address);
- /* Don't use pte_page here, because the mappings can point
- outside mem_map, and the NUMA hash lookup cannot handle
- that. */
- if (!pte_present(*pte) || pte_pfn(*pte) != pte_pfn(*pte_ref))
- BUG();
- return 0;
-#endif
+ return ret;
}
int show_unhandled_signals = 1;
-static inline int access_error(unsigned long error_code, int write,
- struct vm_area_struct *vma)
+static inline int
+access_error(unsigned long error_code, int write, struct vm_area_struct *vma)
{
if (write) {
- /* write, present and write, not present */
+ /* write, present and write, not present: */
if (unlikely(!(vma->vm_flags & VM_WRITE)))
return 1;
- } else if (unlikely(error_code & PF_PROT)) {
- /* read, present */
- return 1;
- } else {
- /* read, not present */
- if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))))
- return 1;
+ return 0;
}
+ /* read, present: */
+ if (unlikely(error_code & PF_PROT))
+ return 1;
+
+ /* read, not present: */
+ if (unlikely(!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))))
+ return 1;
+
return 0;
}
static int fault_in_kernel_space(unsigned long address)
{
-#ifdef CONFIG_X86_32
- return address >= TASK_SIZE;
-#else /* !CONFIG_X86_32 */
- return address >= TASK_SIZE64;
-#endif /* CONFIG_X86_32 */
+ return address >= TASK_SIZE_MAX;
}
/*
@@ -796,23 +968,22 @@ static int fault_in_kernel_space(unsigned long address)
* and the problem, and then passes it off to one of the appropriate
* routines.
*/
-#ifdef CONFIG_X86_64
-asmlinkage
-#endif
-void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
+dotraplinkage void __kprobes
+do_page_fault(struct pt_regs *regs, unsigned long error_code)
{
- unsigned long address;
+ struct vm_area_struct *vma;
struct task_struct *tsk;
+ unsigned long address;
struct mm_struct *mm;
- struct vm_area_struct *vma;
int write;
int fault;
tsk = current;
mm = tsk->mm;
+
prefetchw(&mm->mmap_sem);
- /* get the address */
+ /* Get the faulting address: */
address = read_cr2();
if (unlikely(kmmio_fault(regs, address)))
@@ -836,22 +1007,23 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
vmalloc_fault(address) >= 0)
return;
- /* Can handle a stale RO->RW TLB */
+ /* Can handle a stale RO->RW TLB: */
if (spurious_fault(error_code, address))
return;
- /* kprobes don't want to hook the spurious faults. */
+ /* kprobes don't want to hook the spurious faults: */
if (notify_page_fault(regs))
return;
/*
* Don't take the mm semaphore here. If we fixup a prefetch
- * fault we could otherwise deadlock.
+ * fault we could otherwise deadlock:
*/
bad_area_nosemaphore(regs, error_code, address);
+
return;
}
- /* kprobes don't want to hook the spurious faults. */
+ /* kprobes don't want to hook the spurious faults: */
if (unlikely(notify_page_fault(regs)))
return;
/*
@@ -859,22 +1031,22 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
* vmalloc fault has been handled.
*
* User-mode registers count as a user access even for any
- * potential system fault or CPU buglet.
+ * potential system fault or CPU buglet:
*/
if (user_mode_vm(regs)) {
local_irq_enable();
error_code |= PF_USER;
- } else if (regs->flags & X86_EFLAGS_IF)
- local_irq_enable();
+ } else {
+ if (regs->flags & X86_EFLAGS_IF)
+ local_irq_enable();
+ }
-#ifdef CONFIG_X86_64
if (unlikely(error_code & PF_RSVD))
pgtable_bad(regs, error_code, address);
-#endif
/*
- * If we're in an interrupt, have no user context or are running in an
- * atomic region then we must not take the fault.
+ * If we're in an interrupt, have no user context or are running
+ * in an atomic region then we must not take the fault:
*/
if (unlikely(in_atomic() || !mm)) {
bad_area_nosemaphore(regs, error_code, address);
@@ -883,19 +1055,19 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
/*
* When running in the kernel we expect faults to occur only to
- * addresses in user space. All other faults represent errors in the
- * kernel and should generate an OOPS. Unfortunately, in the case of an
- * erroneous fault occurring in a code path which already holds mmap_sem
- * we will deadlock attempting to validate the fault against the
- * address space. Luckily the kernel only validly references user
- * space from well defined areas of code, which are listed in the
- * exceptions table.
+ * addresses in user space. All other faults represent errors in
+ * the kernel and should generate an OOPS. Unfortunately, in the
+ * case of an erroneous fault occurring in a code path which already
+ * holds mmap_sem we will deadlock attempting to validate the fault
+ * against the address space. Luckily the kernel only validly
+ * references user space from well defined areas of code, which are
+ * listed in the exceptions table.
*
* As the vast majority of faults will be valid we will only perform
- * the source reference check when there is a possibility of a deadlock.
- * Attempt to lock the address space, if we cannot we then validate the
- * source. If this is invalid we can skip the address space check,
- * thus avoiding the deadlock.
+ * the source reference check when there is a possibility of a
+ * deadlock. Attempt to lock the address space, if we cannot we then
+ * validate the source. If this is invalid we can skip the address
+ * space check, thus avoiding the deadlock:
*/
if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
if ((error_code & PF_USER) == 0 &&
@@ -906,8 +1078,9 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
down_read(&mm->mmap_sem);
} else {
/*
- * The above down_read_trylock() might have succeeded in which
- * case we'll have missed the might_sleep() from down_read().
+ * The above down_read_trylock() might have succeeded in
+ * which case we'll have missed the might_sleep() from
+ * down_read():
*/
might_sleep();
}
@@ -927,7 +1100,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
/*
* Accessing the stack below %sp is always a bug.
* The large cushion allows instructions like enter
- * and pusha to work. ("enter $65535,$31" pushes
+ * and pusha to work. ("enter $65535, $31" pushes
* 32 pointers and then decrements %sp by 65535.)
*/
if (unlikely(address + 65536 + 32 * sizeof(unsigned long) < regs->sp)) {
@@ -946,6 +1119,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
*/
good_area:
write = error_code & PF_WRITE;
+
if (unlikely(access_error(error_code, write, vma))) {
bad_area_access_error(regs, error_code, address);
return;
@@ -954,75 +1128,21 @@ good_area:
/*
* If for any reason at all we couldn't handle the fault,
* make sure we exit gracefully rather than endlessly redo
- * the fault.
+ * the fault:
*/
fault = handle_mm_fault(mm, vma, address, write);
+
if (unlikely(fault & VM_FAULT_ERROR)) {
mm_fault_error(regs, error_code, address, fault);
return;
}
+
if (fault & VM_FAULT_MAJOR)
tsk->maj_flt++;
else
tsk->min_flt++;
-#ifdef CONFIG_X86_32
- /*
- * Did it hit the DOS screen memory VA from vm86 mode?
- */
- if (v8086_mode(regs)) {
- unsigned long bit = (address - 0xA0000) >> PAGE_SHIFT;
- if (bit < 32)
- tsk->thread.screen_bitmap |= 1 << bit;
- }
-#endif
- up_read(&mm->mmap_sem);
-}
-
-DEFINE_SPINLOCK(pgd_lock);
-LIST_HEAD(pgd_list);
+ check_v8086_mode(regs, address, tsk);
-void vmalloc_sync_all(void)
-{
- unsigned long address;
-
-#ifdef CONFIG_X86_32
- if (SHARED_KERNEL_PMD)
- return;
-
- for (address = VMALLOC_START & PMD_MASK;
- address >= TASK_SIZE && address < FIXADDR_TOP;
- address += PMD_SIZE) {
- unsigned long flags;
- struct page *page;
-
- spin_lock_irqsave(&pgd_lock, flags);
- list_for_each_entry(page, &pgd_list, lru) {
- if (!vmalloc_sync_one(page_address(page),
- address))
- break;
- }
- spin_unlock_irqrestore(&pgd_lock, flags);
- }
-#else /* CONFIG_X86_64 */
- for (address = VMALLOC_START & PGDIR_MASK; address <= VMALLOC_END;
- address += PGDIR_SIZE) {
- const pgd_t *pgd_ref = pgd_offset_k(address);
- unsigned long flags;
- struct page *page;
-
- if (pgd_none(*pgd_ref))
- continue;
- spin_lock_irqsave(&pgd_lock, flags);
- list_for_each_entry(page, &pgd_list, lru) {
- pgd_t *pgd;
- pgd = (pgd_t *)page_address(page) + pgd_index(address);
- if (pgd_none(*pgd))
- set_pgd(pgd, *pgd_ref);
- else
- BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref));
- }
- spin_unlock_irqrestore(&pgd_lock, flags);
- }
-#endif
+ up_read(&mm->mmap_sem);
}
diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c
index d1f7439d173c..3957cd6d6454 100644
--- a/arch/x86/mm/numa_32.c
+++ b/arch/x86/mm/numa_32.c
@@ -194,7 +194,7 @@ void *alloc_remap(int nid, unsigned long size)
size = ALIGN(size, L1_CACHE_BYTES);
if (!allocation || (allocation + size) >= node_remap_end_vaddr[nid])
- return 0;
+ return NULL;
node_remap_alloc_vaddr[nid] += size;
memset(allocation, 0, size);
diff --git a/arch/x86/mm/numa_64.c b/arch/x86/mm/numa_64.c
index deb1c1ab7868..64c9cf043cdd 100644
--- a/arch/x86/mm/numa_64.c
+++ b/arch/x86/mm/numa_64.c
@@ -166,7 +166,7 @@ int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
return shift;
}
-int early_pfn_to_nid(unsigned long pfn)
+int __meminit __early_pfn_to_nid(unsigned long pfn)
{
return phys_to_nid(pfn << PAGE_SHIFT);
}
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index 8ca0d8566fc8..8253bc97587e 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -482,6 +482,13 @@ static int split_large_page(pte_t *kpte, unsigned long address)
pbase = (pte_t *)page_address(base);
paravirt_alloc_pte(&init_mm, page_to_pfn(base));
ref_prot = pte_pgprot(pte_clrhuge(*kpte));
+ /*
+ * If we ever want to utilize the PAT bit, we need to
+ * update this function to make sure it's converted from
+ * bit 12 to bit 7 when we cross from the 2MB level to
+ * the 4K level:
+ */
+ WARN_ON_ONCE(pgprot_val(ref_prot) & _PAGE_PAT_LARGE);
#ifdef CONFIG_X86_64
if (level == PG_LEVEL_1G) {
@@ -508,18 +515,13 @@ static int split_large_page(pte_t *kpte, unsigned long address)
#endif
/*
- * Install the new, split up pagetable. Important details here:
- *
- * On Intel the NX bit of all levels must be cleared to make a
- * page executable. See section 4.13.2 of Intel 64 and IA-32
- * Architectures Software Developer's Manual).
+ * Install the new, split up pagetable.
*
- * Mark the entry present. The current mapping might be
- * set to not present, which we preserved above.
+ * We use the standard kernel pagetable protections for the new
+ * pagetable protections, the actual ptes set above control the
+ * primary protection behavior:
*/
- ref_prot = pte_pgprot(pte_mkexec(pte_clrhuge(*kpte)));
- pgprot_val(ref_prot) |= _PAGE_PRESENT;
- __set_pmd_pte(kpte, address, mk_pte(base, ref_prot));
+ __set_pmd_pte(kpte, address, mk_pte(base, __pgprot(_KERNPG_TABLE)));
base = NULL;
out_unlock:
diff --git a/arch/x86/mm/srat_64.c b/arch/x86/mm/srat_64.c
index 15df1baee100..574c8bc95ef0 100644
--- a/arch/x86/mm/srat_64.c
+++ b/arch/x86/mm/srat_64.c
@@ -20,7 +20,7 @@
#include <asm/proto.h>
#include <asm/numa.h>
#include <asm/e820.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
#include <asm/uv/uv.h>
int acpi_numa __initdata;
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 14c5af4d11e6..a654d59e4483 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -14,7 +14,6 @@
DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate)
= { &init_mm, 0, };
-#include <asm/genapic.h>
/*
* Smarter SMP flushing macros.
* c/o Linus Torvalds.
diff --git a/arch/x86/pci/numaq_32.c b/arch/x86/pci/numaq_32.c
index 5601e829c387..8eb295e116f6 100644
--- a/arch/x86/pci/numaq_32.c
+++ b/arch/x86/pci/numaq_32.c
@@ -5,7 +5,7 @@
#include <linux/pci.h>
#include <linux/init.h>
#include <linux/nodemask.h>
-#include <asm/genapic.h>
+#include <asm/apic.h>
#include <asm/mpspec.h>
#include <asm/pci_x86.h>
diff --git a/arch/x86/power/hibernate_asm_32.S b/arch/x86/power/hibernate_asm_32.S
index d1e9b53f9d33..b641388d8286 100644
--- a/arch/x86/power/hibernate_asm_32.S
+++ b/arch/x86/power/hibernate_asm_32.S
@@ -8,7 +8,7 @@
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/asm-offsets.h>
#include <asm/processor-flags.h>
diff --git a/arch/x86/power/hibernate_asm_64.S b/arch/x86/power/hibernate_asm_64.S
index 000415947d93..9356547d8c01 100644
--- a/arch/x86/power/hibernate_asm_64.S
+++ b/arch/x86/power/hibernate_asm_64.S
@@ -18,7 +18,7 @@
.text
#include <linux/linkage.h>
#include <asm/segment.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <asm/asm-offsets.h>
#include <asm/processor-flags.h>
diff --git a/arch/x86/vdso/vma.c b/arch/x86/vdso/vma.c
index 9c98cc6ba978..7133cdf9098b 100644
--- a/arch/x86/vdso/vma.c
+++ b/arch/x86/vdso/vma.c
@@ -85,8 +85,8 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
unsigned long addr, end;
unsigned offset;
end = (start + PMD_SIZE - 1) & PMD_MASK;
- if (end >= TASK_SIZE64)
- end = TASK_SIZE64;
+ if (end >= TASK_SIZE_MAX)
+ end = TASK_SIZE_MAX;
end -= len;
/* This loses some more bits than a modulo, but is cheaper */
offset = get_random_int() & (PTRS_PER_PTE - 1);
diff --git a/arch/x86/xen/Kconfig b/arch/x86/xen/Kconfig
index 87b9ab166423..b83e119fbeb0 100644
--- a/arch/x86/xen/Kconfig
+++ b/arch/x86/xen/Kconfig
@@ -6,7 +6,7 @@ config XEN
bool "Xen guest support"
select PARAVIRT
select PARAVIRT_CLOCK
- depends on X86_64 || (X86_32 && X86_PAE && !(X86_VISWS || X86_VOYAGER))
+ depends on X86_64 || (X86_32 && X86_PAE && !X86_VISWS)
depends on X86_CMPXCHG && X86_TSC
help
This is the Linux Xen port. Enabling this will allow the
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 95ff6a0e942a..86497d5f44cd 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -554,14 +554,15 @@ static u32 xen_safe_apic_wait_icr_idle(void)
return 0;
}
-static struct apic_ops xen_basic_apic_ops = {
- .read = xen_apic_read,
- .write = xen_apic_write,
- .icr_read = xen_apic_icr_read,
- .icr_write = xen_apic_icr_write,
- .wait_icr_idle = xen_apic_wait_icr_idle,
- .safe_wait_icr_idle = xen_safe_apic_wait_icr_idle,
-};
+static void set_xen_basic_apic_ops(void)
+{
+ apic->read = xen_apic_read;
+ apic->write = xen_apic_write;
+ apic->icr_read = xen_apic_icr_read;
+ apic->icr_write = xen_apic_icr_write;
+ apic->wait_icr_idle = xen_apic_wait_icr_idle;
+ apic->safe_wait_icr_idle = xen_safe_apic_wait_icr_idle;
+}
#endif
@@ -898,7 +899,7 @@ asmlinkage void __init xen_start_kernel(void)
/*
* set up the basic apic ops.
*/
- apic_ops = &xen_basic_apic_ops;
+ set_xen_basic_apic_ops();
#endif
if (xen_feature(XENFEAT_mmu_pt_update_preserve_ad)) {
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 63d49a523ed3..1a5ff24e29c0 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -8,7 +8,7 @@
#include <asm/boot.h>
#include <asm/asm.h>
-#include <asm/page.h>
+#include <asm/page_types.h>
#include <xen/interface/elfnote.h>
#include <asm/xen/interface.h>
diff --git a/block/blk-timeout.c b/block/blk-timeout.c
index a09535377a94..bbbdc4b8ccf2 100644
--- a/block/blk-timeout.c
+++ b/block/blk-timeout.c
@@ -209,12 +209,19 @@ void blk_abort_queue(struct request_queue *q)
{
unsigned long flags;
struct request *rq, *tmp;
+ LIST_HEAD(list);
spin_lock_irqsave(q->queue_lock, flags);
elv_abort_queue(q);
- list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list)
+ /*
+ * Splice entries to local list, to avoid deadlocking if entries
+ * get readded to the timeout list by error handling
+ */
+ list_splice_init(&q->timeout_list, &list);
+
+ list_for_each_entry_safe(rq, tmp, &list, timeout_list)
blk_abort_request(rq);
spin_unlock_irqrestore(q->queue_lock, flags);
diff --git a/block/blktrace.c b/block/blktrace.c
index 39cc3bfe56e4..7cf9d1ff45a0 100644
--- a/block/blktrace.c
+++ b/block/blktrace.c
@@ -142,7 +142,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes,
what |= ddir_act[rw & WRITE];
what |= MASK_TC_BIT(rw, BARRIER);
- what |= MASK_TC_BIT(rw, SYNC);
+ what |= MASK_TC_BIT(rw, SYNCIO);
what |= MASK_TC_BIT(rw, AHEAD);
what |= MASK_TC_BIT(rw, META);
what |= MASK_TC_BIT(rw, DISCARD);
diff --git a/block/bsg.c b/block/bsg.c
index d414bb5607e8..0ce8806dd0c1 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -244,7 +244,8 @@ bsg_validate_sgv4_hdr(struct request_queue *q, struct sg_io_v4 *hdr, int *rw)
* map sg_io_v4 to a request.
*/
static struct request *
-bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm)
+bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm,
+ u8 *sense)
{
struct request_queue *q = bd->queue;
struct request *rq, *next_rq = NULL;
@@ -306,6 +307,10 @@ bsg_map_hdr(struct bsg_device *bd, struct sg_io_v4 *hdr, fmode_t has_write_perm)
if (ret)
goto out;
}
+
+ rq->sense = sense;
+ rq->sense_len = 0;
+
return rq;
out:
if (rq->cmd != rq->__cmd)
@@ -348,9 +353,6 @@ static void bsg_rq_end_io(struct request *rq, int uptodate)
static void bsg_add_command(struct bsg_device *bd, struct request_queue *q,
struct bsg_command *bc, struct request *rq)
{
- rq->sense = bc->sense;
- rq->sense_len = 0;
-
/*
* add bc command to busy queue and submit rq for io
*/
@@ -419,7 +421,7 @@ static int blk_complete_sgv4_hdr_rq(struct request *rq, struct sg_io_v4 *hdr,
{
int ret = 0;
- dprintk("rq %p bio %p %u\n", rq, bio, rq->errors);
+ dprintk("rq %p bio %p 0x%x\n", rq, bio, rq->errors);
/*
* fill in all the output members
*/
@@ -635,7 +637,7 @@ static int __bsg_write(struct bsg_device *bd, const char __user *buf,
/*
* get a request, fill in the blanks, and add to request queue
*/
- rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm);
+ rq = bsg_map_hdr(bd, &bc->hdr, has_write_perm, bc->sense);
if (IS_ERR(rq)) {
ret = PTR_ERR(rq);
rq = NULL;
@@ -922,11 +924,12 @@ static long bsg_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
struct request *rq;
struct bio *bio, *bidi_bio = NULL;
struct sg_io_v4 hdr;
+ u8 sense[SCSI_SENSE_BUFFERSIZE];
if (copy_from_user(&hdr, uarg, sizeof(hdr)))
return -EFAULT;
- rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE);
+ rq = bsg_map_hdr(bd, &hdr, file->f_mode & FMODE_WRITE, sense);
if (IS_ERR(rq))
return PTR_ERR(rq);
diff --git a/block/genhd.c b/block/genhd.c
index 397960cf26af..e1eadcc9546a 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1087,6 +1087,14 @@ dev_t blk_lookup_devt(const char *name, int partno)
if (strcmp(dev_name(dev), name))
continue;
+ if (partno < disk->minors) {
+ /* We need to return the right devno, even
+ * if the partition doesn't exist yet.
+ */
+ devt = MKDEV(MAJOR(dev->devt),
+ MINOR(dev->devt) + partno);
+ break;
+ }
part = disk_get_part(disk, partno);
if (part) {
devt = part_devt(part);
diff --git a/crypto/lrw.c b/crypto/lrw.c
index 8ef664e3bcd9..358f80be2bf9 100644
--- a/crypto/lrw.c
+++ b/crypto/lrw.c
@@ -45,7 +45,13 @@ struct priv {
static inline void setbit128_bbe(void *b, int bit)
{
- __set_bit(bit ^ 0x78, b);
+ __set_bit(bit ^ (0x80 -
+#ifdef __BIG_ENDIAN
+ BITS_PER_LONG
+#else
+ BITS_PER_BYTE
+#endif
+ ), b);
}
static int setkey(struct crypto_tfm *parent, const u8 *key,
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index a7799a99f2d9..8a851d0f4384 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -254,13 +254,6 @@ config ACPI_PCI_SLOT
help you correlate PCI bus addresses with the physical geography
of your slots. If you are unsure, say N.
-config ACPI_SYSTEM
- bool
- default y
- help
- This driver will enable your system to shut down using ACPI, and
- dump your ACPI DSDT table using /proc/acpi/dsdt.
-
config X86_PM_TIMER
bool "Power Management Timer Support" if EMBEDDED
depends on X86
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 65d90c720b5a..b130ea0d0759 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -52,7 +52,7 @@ obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-$(CONFIG_ACPI_CONTAINER) += container.o
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
obj-y += power.o
-obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o
+obj-y += system.o event.o
obj-$(CONFIG_ACPI_DEBUG) += debug.o
obj-$(CONFIG_ACPI_NUMA) += numa.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 65132f920459..69cbc57c2d1c 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -138,6 +138,29 @@ static int acpi_battery_technology(struct acpi_battery *battery)
static int acpi_battery_get_state(struct acpi_battery *battery);
+static int acpi_battery_is_charged(struct acpi_battery *battery)
+{
+ /* either charging or discharging */
+ if (battery->state != 0)
+ return 0;
+
+ /* battery not reporting charge */
+ if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN ||
+ battery->capacity_now == 0)
+ return 0;
+
+ /* good batteries update full_charge as the batteries degrade */
+ if (battery->full_charge_capacity == battery->capacity_now)
+ return 1;
+
+ /* fallback to using design values for broken batteries */
+ if (battery->design_capacity == battery->capacity_now)
+ return 1;
+
+ /* we don't do any sort of metric based on percentages */
+ return 0;
+}
+
static int acpi_battery_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -155,7 +178,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
else if (battery->state & 0x02)
val->intval = POWER_SUPPLY_STATUS_CHARGING;
- else if (battery->state == 0)
+ else if (acpi_battery_is_charged(battery))
val->intval = POWER_SUPPLY_STATUS_FULL;
else
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 5c2f5d343be6..2fe15060dcdc 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -120,6 +120,8 @@ static struct acpi_ec {
spinlock_t curr_lock;
} *boot_ec, *first_ec;
+static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */
+
/* --------------------------------------------------------------------------
Transaction Management
-------------------------------------------------------------------------- */
@@ -259,6 +261,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec,
clear_bit(EC_FLAGS_GPE_MODE, &ec->flags);
acpi_disable_gpe(NULL, ec->gpe);
}
+ if (EC_FLAGS_MSI)
+ udelay(ACPI_EC_DELAY);
/* start transaction */
spin_lock_irqsave(&ec->curr_lock, tmp);
/* following two actions should be kept atomic */
@@ -967,6 +971,11 @@ int __init acpi_ec_ecdt_probe(void)
/*
* Generate a boot ec context
*/
+ if (dmi_name_in_vendors("Micro-Star") ||
+ dmi_name_in_vendors("Notebook")) {
+ pr_info(PREFIX "Enabling special treatment for EC from MSI.\n");
+ EC_FLAGS_MSI = 1;
+ }
status = acpi_get_table(ACPI_SIG_ECDT, 1,
(struct acpi_table_header **)&ecdt_ptr);
if (ACPI_SUCCESS(status)) {
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index d1dd5160daa9..2b6c59028254 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -272,7 +272,7 @@ acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
}
EXPORT_SYMBOL_GPL(acpi_os_map_memory);
-void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
+void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
{
if (acpi_gbl_permanent_mmap)
iounmap(virt);
@@ -281,7 +281,7 @@ void acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
}
EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
-void early_acpi_os_unmap_memory(void __iomem * virt, acpi_size size)
+void __init early_acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
{
if (!acpi_gbl_permanent_mmap)
__acpi_unmap_table(virt, size);
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 0b299b0f8172..714cb046b594 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -773,18 +773,32 @@ unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
else
iowrite32_rep(data_addr, buf, words);
+ /* Transfer trailing bytes, if any */
if (unlikely(slop)) {
- __le32 pad;
+ unsigned char pad[4];
+
+ /* Point buf to the tail of buffer */
+ buf += buflen - slop;
+
+ /*
+ * Use io*_rep() accessors here as well to avoid pointlessly
+ * swapping bytes to and fro on the big endian machines...
+ */
if (rw == READ) {
- pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
- memcpy(buf + buflen - slop, &pad, slop);
+ if (slop < 3)
+ ioread16_rep(data_addr, pad, 1);
+ else
+ ioread32_rep(data_addr, pad, 1);
+ memcpy(buf, pad, slop);
} else {
- memcpy(&pad, buf + buflen - slop, slop);
- iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
+ memcpy(pad, buf, slop);
+ if (slop < 3)
+ iowrite16_rep(data_addr, pad, 1);
+ else
+ iowrite32_rep(data_addr, pad, 1);
}
- words++;
}
- return words << 2;
+ return (buflen + 1) & ~1;
}
EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 79a6c9a0b721..ba556d3e6963 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -110,7 +110,8 @@ static const struct via_isa_bridge {
{ "vt8237s", PCI_DEVICE_ID_VIA_8237S, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
- { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES},
+ { "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
+ { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
{ "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
@@ -593,6 +594,7 @@ static int via_reinit_one(struct pci_dev *pdev)
#endif
static const struct pci_device_id via[] = {
+ { PCI_VDEVICE(VIA, 0x0415), },
{ PCI_VDEVICE(VIA, 0x0571), },
{ PCI_VDEVICE(VIA, 0x0581), },
{ PCI_VDEVICE(VIA, 0x1571), },
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 444af0415ca1..55a8eed3f3a3 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -421,19 +421,21 @@ static struct ata_port_operations nv_generic_ops = {
.hardreset = ATA_OP_NULL,
};
-/* OSDL bz3352 reports that nf2/3 controllers can't determine device
- * signature reliably. Also, the following thread reports detection
- * failure on cold boot with the standard debouncing timing.
+/* nf2 is ripe with hardreset related problems.
+ *
+ * kernel bz#3352 reports nf2/3 controllers can't determine device
+ * signature reliably. The following thread reports detection failure
+ * on cold boot with the standard debouncing timing.
*
* http://thread.gmane.org/gmane.linux.ide/34098
*
- * Debounce with hotplug timing and request follow-up SRST.
+ * And bz#12176 reports that hardreset simply doesn't work on nf2.
+ * Give up on it and just don't do hardreset.
*/
static struct ata_port_operations nv_nf2_ops = {
- .inherits = &nv_common_ops,
+ .inherits = &nv_generic_ops,
.freeze = nv_nf2_freeze,
.thaw = nv_nf2_thaw,
- .hardreset = nv_noclassify_hardreset,
};
/* For initial probing after boot and hot plugging, hardreset mostly
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 0a5f055dffba..9f50f1b545dc 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -88,8 +88,6 @@ extern void driver_detach(struct device_driver *drv);
extern int driver_probe_device(struct device_driver *drv, struct device *dev);
extern void sysdev_shutdown(void);
-extern int sysdev_suspend(pm_message_t state);
-extern int sysdev_resume(void);
extern char *make_class_name(const char *name, struct kobject *kobj);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 315bed8d5e7f..135231239103 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -18,9 +18,11 @@
*/
#include <linux/device.h>
+#include <linux/delay.h>
#include <linux/module.h>
#include <linux/kthread.h>
#include <linux/wait.h>
+#include <linux/async.h>
#include "base.h"
#include "power/power.h"
@@ -168,6 +170,21 @@ int driver_probe_done(void)
}
/**
+ * wait_for_device_probe
+ * Wait for device probing to be completed.
+ *
+ * Note: this function polls at 100 msec intervals.
+ */
+int wait_for_device_probe(void)
+{
+ /* wait for the known devices to complete their probing */
+ while (driver_probe_done() != 0)
+ msleep(100);
+ async_synchronize_full();
+ return 0;
+}
+
+/**
* driver_probe_device - attempt to bind device & driver together
* @drv: driver to bind a device to
* @dev: device to try to bind to the driver
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 670c9d6c1407..2d14f4ae6c01 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -333,7 +333,6 @@ static void dpm_power_up(pm_message_t state)
*/
void device_power_up(pm_message_t state)
{
- sysdev_resume();
dpm_power_up(state);
}
EXPORT_SYMBOL_GPL(device_power_up);
@@ -577,8 +576,6 @@ int device_power_down(pm_message_t state)
}
dev->power.status = DPM_OFF_IRQ;
}
- if (!error)
- error = sysdev_suspend(state);
if (error)
dpm_power_up(resume_event(state));
return error;
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index c98c31ec2f75..b428c8c4bc64 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -303,7 +303,6 @@ void sysdev_unregister(struct sys_device * sysdev)
* is guaranteed by virtue of the fact that child devices are registered
* after their parents.
*/
-
void sysdev_shutdown(void)
{
struct sysdev_class * cls;
@@ -363,7 +362,6 @@ static void __sysdev_resume(struct sys_device *dev)
* This is only called by the device PM core, so we let them handle
* all synchronization.
*/
-
int sysdev_suspend(pm_message_t state)
{
struct sysdev_class * cls;
@@ -432,7 +430,7 @@ aux_driver:
}
return ret;
}
-
+EXPORT_SYMBOL_GPL(sysdev_suspend);
/**
* sysdev_resume - Bring system devices back to life.
@@ -442,7 +440,6 @@ aux_driver:
*
* Note: Interrupts are disabled when called.
*/
-
int sysdev_resume(void)
{
struct sysdev_class * cls;
@@ -463,7 +460,7 @@ int sysdev_resume(void)
}
return 0;
}
-
+EXPORT_SYMBOL_GPL(sysdev_resume);
int __init system_bus_init(void)
{
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index c237527b1aa5..5e41e6dd657b 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -18,6 +18,7 @@
enum {
AOECMD_ATA,
AOECMD_CFG,
+ AOECMD_VEND_MIN = 0xf0,
AOEFL_RSP = (1<<3),
AOEFL_ERR = (1<<2),
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index 30de5b1c647e..c6099ba9a4b8 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -142,6 +142,8 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
aoecmd_cfg_rsp(skb);
break;
default:
+ if (h->cmd >= AOECMD_VEND_MIN)
+ break; /* don't complain about vendor commands */
printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
}
exit:
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index 69e1df7dfa14..4234c11c1e4c 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -1730,7 +1730,7 @@ static int __init fd_test_drive_present( int drive )
timeout = jiffies + 2*HZ+HZ/2;
while (time_before(jiffies, timeout))
- if (!(mfp.par_dt_reg & 0x20))
+ if (!(st_mfp.par_dt_reg & 0x20))
break;
status = FDC_READ( FDCREG_STATUS );
@@ -1747,7 +1747,7 @@ static int __init fd_test_drive_present( int drive )
/* dummy seek command to make WP bit accessible */
FDC_WRITE( FDCREG_DATA, 0 );
FDC_WRITE( FDCREG_CMD, FDCCMD_SEEK );
- while( mfp.par_dt_reg & 0x20 )
+ while( st_mfp.par_dt_reg & 0x20 )
;
status = FDC_READ( FDCREG_STATUS );
}
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 01e69383d9c0..d2cb67b61176 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -3390,6 +3390,203 @@ static void free_hba(int i)
kfree(p);
}
+/* Send a message CDB to the firmware. */
+static __devinit int cciss_message(struct pci_dev *pdev, unsigned char opcode, unsigned char type)
+{
+ typedef struct {
+ CommandListHeader_struct CommandHeader;
+ RequestBlock_struct Request;
+ ErrDescriptor_struct ErrorDescriptor;
+ } Command;
+ static const size_t cmd_sz = sizeof(Command) + sizeof(ErrorInfo_struct);
+ Command *cmd;
+ dma_addr_t paddr64;
+ uint32_t paddr32, tag;
+ void __iomem *vaddr;
+ int i, err;
+
+ vaddr = ioremap_nocache(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
+ if (vaddr == NULL)
+ return -ENOMEM;
+
+ /* The Inbound Post Queue only accepts 32-bit physical addresses for the
+ CCISS commands, so they must be allocated from the lower 4GiB of
+ memory. */
+ err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+ if (err) {
+ iounmap(vaddr);
+ return -ENOMEM;
+ }
+
+ cmd = pci_alloc_consistent(pdev, cmd_sz, &paddr64);
+ if (cmd == NULL) {
+ iounmap(vaddr);
+ return -ENOMEM;
+ }
+
+ /* This must fit, because of the 32-bit consistent DMA mask. Also,
+ although there's no guarantee, we assume that the address is at
+ least 4-byte aligned (most likely, it's page-aligned). */
+ paddr32 = paddr64;
+
+ cmd->CommandHeader.ReplyQueue = 0;
+ cmd->CommandHeader.SGList = 0;
+ cmd->CommandHeader.SGTotal = 0;
+ cmd->CommandHeader.Tag.lower = paddr32;
+ cmd->CommandHeader.Tag.upper = 0;
+ memset(&cmd->CommandHeader.LUN.LunAddrBytes, 0, 8);
+
+ cmd->Request.CDBLen = 16;
+ cmd->Request.Type.Type = TYPE_MSG;
+ cmd->Request.Type.Attribute = ATTR_HEADOFQUEUE;
+ cmd->Request.Type.Direction = XFER_NONE;
+ cmd->Request.Timeout = 0; /* Don't time out */
+ cmd->Request.CDB[0] = opcode;
+ cmd->Request.CDB[1] = type;
+ memset(&cmd->Request.CDB[2], 0, 14); /* the rest of the CDB is reserved */
+
+ cmd->ErrorDescriptor.Addr.lower = paddr32 + sizeof(Command);
+ cmd->ErrorDescriptor.Addr.upper = 0;
+ cmd->ErrorDescriptor.Len = sizeof(ErrorInfo_struct);
+
+ writel(paddr32, vaddr + SA5_REQUEST_PORT_OFFSET);
+
+ for (i = 0; i < 10; i++) {
+ tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
+ if ((tag & ~3) == paddr32)
+ break;
+ schedule_timeout_uninterruptible(HZ);
+ }
+
+ iounmap(vaddr);
+
+ /* we leak the DMA buffer here ... no choice since the controller could
+ still complete the command. */
+ if (i == 10) {
+ printk(KERN_ERR "cciss: controller message %02x:%02x timed out\n",
+ opcode, type);
+ return -ETIMEDOUT;
+ }
+
+ pci_free_consistent(pdev, cmd_sz, cmd, paddr64);
+
+ if (tag & 2) {
+ printk(KERN_ERR "cciss: controller message %02x:%02x failed\n",
+ opcode, type);
+ return -EIO;
+ }
+
+ printk(KERN_INFO "cciss: controller message %02x:%02x succeeded\n",
+ opcode, type);
+ return 0;
+}
+
+#define cciss_soft_reset_controller(p) cciss_message(p, 1, 0)
+#define cciss_noop(p) cciss_message(p, 3, 0)
+
+static __devinit int cciss_reset_msi(struct pci_dev *pdev)
+{
+/* the #defines are stolen from drivers/pci/msi.h. */
+#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
+#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
+
+ int pos;
+ u16 control = 0;
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
+ if (pos) {
+ pci_read_config_word(pdev, msi_control_reg(pos), &control);
+ if (control & PCI_MSI_FLAGS_ENABLE) {
+ printk(KERN_INFO "cciss: resetting MSI\n");
+ pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSI_FLAGS_ENABLE);
+ }
+ }
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+ if (pos) {
+ pci_read_config_word(pdev, msi_control_reg(pos), &control);
+ if (control & PCI_MSIX_FLAGS_ENABLE) {
+ printk(KERN_INFO "cciss: resetting MSI-X\n");
+ pci_write_config_word(pdev, msi_control_reg(pos), control & ~PCI_MSIX_FLAGS_ENABLE);
+ }
+ }
+
+ return 0;
+}
+
+/* This does a hard reset of the controller using PCI power management
+ * states. */
+static __devinit int cciss_hard_reset_controller(struct pci_dev *pdev)
+{
+ u16 pmcsr, saved_config_space[32];
+ int i, pos;
+
+ printk(KERN_INFO "cciss: using PCI PM to reset controller\n");
+
+ /* This is very nearly the same thing as
+
+ pci_save_state(pci_dev);
+ pci_set_power_state(pci_dev, PCI_D3hot);
+ pci_set_power_state(pci_dev, PCI_D0);
+ pci_restore_state(pci_dev);
+
+ but we can't use these nice canned kernel routines on
+ kexec, because they also check the MSI/MSI-X state in PCI
+ configuration space and do the wrong thing when it is
+ set/cleared. Also, the pci_save/restore_state functions
+ violate the ordering requirements for restoring the
+ configuration space from the CCISS document (see the
+ comment below). So we roll our own .... */
+
+ for (i = 0; i < 32; i++)
+ pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
+
+ pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
+ if (pos == 0) {
+ printk(KERN_ERR "cciss_reset_controller: PCI PM not supported\n");
+ return -ENODEV;
+ }
+
+ /* Quoting from the Open CISS Specification: "The Power
+ * Management Control/Status Register (CSR) controls the power
+ * state of the device. The normal operating state is D0,
+ * CSR=00h. The software off state is D3, CSR=03h. To reset
+ * the controller, place the interface device in D3 then to
+ * D0, this causes a secondary PCI reset which will reset the
+ * controller." */
+
+ /* enter the D3hot power management state */
+ pci_read_config_word(pdev, pos + PCI_PM_CTRL, &pmcsr);
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ pmcsr |= PCI_D3hot;
+ pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+ schedule_timeout_uninterruptible(HZ >> 1);
+
+ /* enter the D0 power management state */
+ pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
+ pmcsr |= PCI_D0;
+ pci_write_config_word(pdev, pos + PCI_PM_CTRL, pmcsr);
+
+ schedule_timeout_uninterruptible(HZ >> 1);
+
+ /* Restore the PCI configuration space. The Open CISS
+ * Specification says, "Restore the PCI Configuration
+ * Registers, offsets 00h through 60h. It is important to
+ * restore the command register, 16-bits at offset 04h,
+ * last. Do not restore the configuration status register,
+ * 16-bits at offset 06h." Note that the offset is 2*i. */
+ for (i = 0; i < 32; i++) {
+ if (i == 2 || i == 3)
+ continue;
+ pci_write_config_word(pdev, 2*i, saved_config_space[i]);
+ }
+ wmb();
+ pci_write_config_word(pdev, 4, saved_config_space[2]);
+
+ return 0;
+}
+
/*
* This is it. Find all the controllers and register them. I really hate
* stealing all these major device numbers.
@@ -3404,6 +3601,24 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
int dac, return_code;
InquiryData_struct *inq_buff = NULL;
+ if (reset_devices) {
+ /* Reset the controller with a PCI power-cycle */
+ if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev))
+ return -ENODEV;
+
+ /* Some devices (notably the HP Smart Array 5i Controller)
+ need a little pause here */
+ schedule_timeout_uninterruptible(30*HZ);
+
+ /* Now try to get the controller to respond to a no-op */
+ for (i=0; i<12; i++) {
+ if (cciss_noop(pdev) == 0)
+ break;
+ else
+ printk("cciss: no-op failed%s\n", (i < 11 ? "; re-trying" : ""));
+ }
+ }
+
i = alloc_cciss_hba();
if (i < 0)
return -1;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index cf29cc4e6ab7..83d8ed39433d 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -558,6 +558,8 @@ static void process_fd_request(void);
static void recalibrate_floppy(void);
static void floppy_shutdown(unsigned long);
+static int floppy_request_regions(int);
+static void floppy_release_regions(int);
static int floppy_grab_irq_and_dma(void);
static void floppy_release_irq_and_dma(void);
@@ -4274,8 +4276,7 @@ static int __init floppy_init(void)
FDCS->rawcmd = 2;
if (user_reset_fdc(-1, FD_RESET_ALWAYS, 0)) {
/* free ioports reserved by floppy_grab_irq_and_dma() */
- release_region(FDCS->address + 2, 4);
- release_region(FDCS->address + 7, 1);
+ floppy_release_regions(fdc);
FDCS->address = -1;
FDCS->version = FDC_NONE;
continue;
@@ -4284,8 +4285,7 @@ static int __init floppy_init(void)
FDCS->version = get_fdc_version();
if (FDCS->version == FDC_NONE) {
/* free ioports reserved by floppy_grab_irq_and_dma() */
- release_region(FDCS->address + 2, 4);
- release_region(FDCS->address + 7, 1);
+ floppy_release_regions(fdc);
FDCS->address = -1;
continue;
}
@@ -4358,6 +4358,47 @@ out_put_disk:
static DEFINE_SPINLOCK(floppy_usage_lock);
+static const struct io_region {
+ int offset;
+ int size;
+} io_regions[] = {
+ { 2, 1 },
+ /* address + 3 is sometimes reserved by pnp bios for motherboard */
+ { 4, 2 },
+ /* address + 6 is reserved, and may be taken by IDE.
+ * Unfortunately, Adaptec doesn't know this :-(, */
+ { 7, 1 },
+};
+
+static void floppy_release_allocated_regions(int fdc, const struct io_region *p)
+{
+ while (p != io_regions) {
+ p--;
+ release_region(FDCS->address + p->offset, p->size);
+ }
+}
+
+#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)]))
+
+static int floppy_request_regions(int fdc)
+{
+ const struct io_region *p;
+
+ for (p = io_regions; p < ARRAY_END(io_regions); p++) {
+ if (!request_region(FDCS->address + p->offset, p->size, "floppy")) {
+ DPRINT("Floppy io-port 0x%04lx in use\n", FDCS->address + p->offset);
+ floppy_release_allocated_regions(fdc, p);
+ return -EBUSY;
+ }
+ }
+ return 0;
+}
+
+static void floppy_release_regions(int fdc)
+{
+ floppy_release_allocated_regions(fdc, ARRAY_END(io_regions));
+}
+
static int floppy_grab_irq_and_dma(void)
{
unsigned long flags;
@@ -4399,18 +4440,8 @@ static int floppy_grab_irq_and_dma(void)
for (fdc = 0; fdc < N_FDC; fdc++) {
if (FDCS->address != -1) {
- if (!request_region(FDCS->address + 2, 4, "floppy")) {
- DPRINT("Floppy io-port 0x%04lx in use\n",
- FDCS->address + 2);
- goto cleanup1;
- }
- if (!request_region(FDCS->address + 7, 1, "floppy DIR")) {
- DPRINT("Floppy io-port 0x%04lx in use\n",
- FDCS->address + 7);
- goto cleanup2;
- }
- /* address + 6 is reserved, and may be taken by IDE.
- * Unfortunately, Adaptec doesn't know this :-(, */
+ if (floppy_request_regions(fdc))
+ goto cleanup;
}
}
for (fdc = 0; fdc < N_FDC; fdc++) {
@@ -4432,15 +4463,11 @@ static int floppy_grab_irq_and_dma(void)
fdc = 0;
irqdma_allocated = 1;
return 0;
-cleanup2:
- release_region(FDCS->address + 2, 4);
-cleanup1:
+cleanup:
fd_free_irq();
fd_free_dma();
- while (--fdc >= 0) {
- release_region(FDCS->address + 2, 4);
- release_region(FDCS->address + 7, 1);
- }
+ while (--fdc >= 0)
+ floppy_release_regions(fdc);
spin_lock_irqsave(&floppy_usage_lock, flags);
usage_count--;
spin_unlock_irqrestore(&floppy_usage_lock, flags);
@@ -4501,10 +4528,8 @@ static void floppy_release_irq_and_dma(void)
#endif
old_fdc = fdc;
for (fdc = 0; fdc < N_FDC; fdc++)
- if (FDCS->address != -1) {
- release_region(FDCS->address + 2, 4);
- release_region(FDCS->address + 7, 1);
- }
+ if (FDCS->address != -1)
+ floppy_release_regions(fdc);
fdc = old_fdc;
}
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 9dfa27163001..c397b3ddba9b 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -422,7 +422,7 @@ static void xs(char *buf, char *targ, int len)
for (k = 0; k < len; k++) {
char c = *buf++;
- if (c != ' ' || c != l)
+ if (c != ' ' && c != l)
l = *targ++ = c;
}
if (l == ' ')
diff --git a/drivers/char/scc.h b/drivers/char/scc.h
index 93998f5baff5..341b1142bea8 100644
--- a/drivers/char/scc.h
+++ b/drivers/char/scc.h
@@ -387,7 +387,7 @@ struct scc_port {
/* The SCC needs 3.5 PCLK cycles recovery time between to register
* accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
* 125 ns = 437.5 ns. This is too short for udelay().
- * 10/16/95: A tstb mfp.par_dt_reg takes 600ns (sure?) and thus should be
+ * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be
* quite right
*/
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index f146e90404fa..518f2a25d91e 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1746,9 +1746,10 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
break;
case SXIO_DO_RAMTEST:
- if (sx_initialized) /* Already initialized: better not ramtest the board. */
+ if (sx_initialized) { /* Already initialized: better not ramtest the board. */
rc = -EPERM;
break;
+ }
if (IS_SX_BOARD(board)) {
rc = do_memtest(board, 0, 0x7000);
if (!rc)
@@ -1788,7 +1789,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
nbytes - i : SX_CHUNK_SIZE)) {
kfree(tmp);
rc = -EFAULT;
- break;
+ goto out;
}
memcpy_toio(board->base2 + offset + i, tmp,
(i + SX_CHUNK_SIZE > nbytes) ?
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index a58993011edb..280a9d263eb3 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -518,6 +518,7 @@ struct dma_chan *__dma_request_channel(dma_cap_mask_t *mask, dma_filter_fn fn, v
dma_chan_name(chan), err);
else
break;
+ chan->private = NULL;
chan = NULL;
}
}
@@ -536,6 +537,7 @@ void dma_release_channel(struct dma_chan *chan)
WARN_ONCE(chan->client_count != 1,
"chan reference count %d != 1\n", chan->client_count);
dma_chan_put(chan);
+ chan->private = NULL;
mutex_unlock(&dma_list_mutex);
}
EXPORT_SYMBOL_GPL(dma_release_channel);
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 6b702cc46b3d..a97c07eef7ec 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -560,7 +560,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned long flags)
{
struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
- struct dw_dma_slave *dws = dwc->dws;
+ struct dw_dma_slave *dws = chan->private;
struct dw_desc *prev;
struct dw_desc *first;
u32 ctllo;
@@ -790,7 +790,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
cfghi = DWC_CFGH_FIFO_MODE;
cfglo = 0;
- dws = dwc->dws;
+ dws = chan->private;
if (dws) {
/*
* We need controller-specific data to set up slave
@@ -866,7 +866,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
spin_lock_bh(&dwc->lock);
list_splice_init(&dwc->free_list, &list);
dwc->descs_allocated = 0;
- dwc->dws = NULL;
/* Disable interrupts */
channel_clear_bit(dw, MASK.XFER, dwc->mask);
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 00fdd187bb0c..b252b202c5cf 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -139,8 +139,6 @@ struct dw_dma_chan {
struct list_head queue;
struct list_head free_list;
- struct dw_dma_slave *dws;
-
unsigned int descs_allocated;
};
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 261b9aa3f248..05aa2d406ac6 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -1,7 +1,7 @@
/*
* linux/drivers/firmware/memmap.c
* Copyright (C) 2008 SUSE LINUX Products GmbH
- * by Bernhard Walle <bwalle@suse.de>
+ * by Bernhard Walle <bernhard.walle@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License v2.0 as published by
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 4be3acbaaf9a..3a22eb9be378 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -80,18 +80,17 @@ config DRM_I915
XFree86 4.4 and above. If unsure, build this and i830 as modules and
the X server will load the correct one.
-endchoice
-
config DRM_I915_KMS
bool "Enable modesetting on intel by default"
depends on DRM_I915
help
- Choose this option if you want kernel modesetting enabled by default,
- and you have a new enough userspace to support this. Running old
- userspaces with this enabled will cause pain. Note that this causes
- the driver to bind to PCI devices, which precludes loading things
- like intelfb.
+ Choose this option if you want kernel modesetting enabled by default,
+ and you have a new enough userspace to support this. Running old
+ userspaces with this enabled will cause pain. Note that this causes
+ the driver to bind to PCI devices, which precludes loading things
+ like intelfb.
+endchoice
config DRM_MGA
tristate "Matrox g200/g400"
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index bfce0992fefb..94a768871734 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1741,9 +1741,8 @@ out:
* RETURNS:
* Zero on success, errno on failure.
*/
-void drm_fb_release(struct file *filp)
+void drm_fb_release(struct drm_file *priv)
{
- struct drm_file *priv = filp->private_data;
struct drm_device *dev = priv->minor->dev;
struct drm_framebuffer *fb, *tfb;
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 964c5eb1fada..733028b4d45e 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -512,8 +512,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
if (drm_mode_equal(&saved_mode, &crtc->mode)) {
if (saved_x != crtc->x || saved_y != crtc->y ||
depth_changed || bpp_changed) {
- crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
- old_fb);
+ ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
+ old_fb);
goto done;
}
}
@@ -552,7 +552,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
/* Set up the DPLL and any encoders state that needs to adjust or depend
* on the DPLL.
*/
- crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+ ret = !crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
+ if (!ret)
+ goto done;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -752,6 +754,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
set->x, set->y,
old_fb)) {
+ DRM_ERROR("failed to set mode on crtc %p\n",
+ set->crtc);
ret = -EINVAL;
goto fail_set_mode;
}
@@ -765,7 +769,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
old_fb = set->crtc->fb;
if (set->crtc->fb != set->fb)
set->crtc->fb = set->fb;
- crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb);
+ ret = crtc_funcs->mode_set_base(set->crtc,
+ set->x, set->y, old_fb);
+ if (ret != 0)
+ goto fail_set_mode;
}
kfree(save_encoders);
@@ -775,8 +782,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
fail_set_mode:
set->crtc->enabled = save_enabled;
count = 0;
- list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ if (!connector->encoder)
+ continue;
+
connector->encoder->crtc = save_crtcs[count++];
+ }
fail_no_encoder:
kfree(save_crtcs);
count = 0;
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index b06a53715853..6c020fe5431c 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -457,6 +457,9 @@ int drm_release(struct inode *inode, struct file *filp)
if (dev->driver->driver_features & DRIVER_GEM)
drm_gem_release(dev, file_priv);
+ if (dev->driver->driver_features & DRIVER_MODESET)
+ drm_fb_release(file_priv);
+
mutex_lock(&dev->ctxlist_mutex);
if (!list_empty(&dev->ctxlist)) {
struct drm_ctx_list *pos, *n;
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 6915fb82d0b0..88d3368ffddd 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -104,8 +104,8 @@ drm_gem_init(struct drm_device *dev)
if (drm_mm_init(&mm->offset_manager, DRM_FILE_PAGE_OFFSET_START,
DRM_FILE_PAGE_OFFSET_SIZE)) {
- drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
drm_ht_remove(&mm->offset_hash);
+ drm_free(mm, sizeof(struct drm_gem_mm), DRM_MEM_MM);
return -ENOMEM;
}
@@ -295,35 +295,37 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data,
return -EBADF;
again:
- if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0)
- return -ENOMEM;
+ if (idr_pre_get(&dev->object_name_idr, GFP_KERNEL) == 0) {
+ ret = -ENOMEM;
+ goto err;
+ }
spin_lock(&dev->object_name_lock);
- if (obj->name) {
- args->name = obj->name;
+ if (!obj->name) {
+ ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
+ &obj->name);
+ args->name = (uint64_t) obj->name;
spin_unlock(&dev->object_name_lock);
- return 0;
- }
- ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
- &obj->name);
- spin_unlock(&dev->object_name_lock);
- if (ret == -EAGAIN)
- goto again;
- if (ret != 0) {
- mutex_lock(&dev->struct_mutex);
- drm_gem_object_unreference(obj);
- mutex_unlock(&dev->struct_mutex);
- return ret;
- }
+ if (ret == -EAGAIN)
+ goto again;
- /*
- * Leave the reference from the lookup around as the
- * name table now holds one
- */
- args->name = (uint64_t) obj->name;
+ if (ret != 0)
+ goto err;
- return 0;
+ /* Allocate a reference for the name table. */
+ drm_gem_object_reference(obj);
+ } else {
+ args->name = (uint64_t) obj->name;
+ spin_unlock(&dev->object_name_lock);
+ ret = 0;
+ }
+
+err:
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
}
/**
@@ -448,6 +450,7 @@ drm_gem_object_handle_free(struct kref *kref)
spin_lock(&dev->object_name_lock);
if (obj->name) {
idr_remove(&dev->object_name_idr, obj->name);
+ obj->name = 0;
spin_unlock(&dev->object_name_lock);
/*
* The object name held a reference to this object, drop
@@ -460,6 +463,26 @@ drm_gem_object_handle_free(struct kref *kref)
}
EXPORT_SYMBOL(drm_gem_object_handle_free);
+void drm_gem_vm_open(struct vm_area_struct *vma)
+{
+ struct drm_gem_object *obj = vma->vm_private_data;
+
+ drm_gem_object_reference(obj);
+}
+EXPORT_SYMBOL(drm_gem_vm_open);
+
+void drm_gem_vm_close(struct vm_area_struct *vma)
+{
+ struct drm_gem_object *obj = vma->vm_private_data;
+ struct drm_device *dev = obj->dev;
+
+ mutex_lock(&dev->struct_mutex);
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
+}
+EXPORT_SYMBOL(drm_gem_vm_close);
+
+
/**
* drm_gem_mmap - memory map routine for GEM objects
* @filp: DRM file pointer
@@ -521,6 +544,14 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
#endif
vma->vm_page_prot = __pgprot(prot);
+ /* Take a ref for this mapping of the object, so that the fault
+ * handler can dereference the mmap offset's pointer to the object.
+ * This reference is cleaned up by the corresponding vm_close
+ * (which should happen whether the vma was created by this call, or
+ * by a vm_open due to mremap or partial unmap or whatever).
+ */
+ drm_gem_object_reference(obj);
+
vma->vm_file = filp; /* Needed for drm_vm_open() */
drm_vm_open_locked(vma);
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c
index 81f1cff56fd5..2d797ffe8137 100644
--- a/drivers/gpu/drm/i915/i915_dma.c
+++ b/drivers/gpu/drm/i915/i915_dma.c
@@ -202,7 +202,7 @@ static int i915_initialize(struct drm_device * dev, drm_i915_init_t * init)
dev_priv->ring.map.flags = 0;
dev_priv->ring.map.mtrr = 0;
- drm_core_ioremap(&dev_priv->ring.map, dev);
+ drm_core_ioremap_wc(&dev_priv->ring.map, dev);
if (dev_priv->ring.map.handle == NULL) {
i915_dma_cleanup(dev);
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index aac12ee31a46..0692622ee2b3 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -27,6 +27,7 @@
*
*/
+#include <linux/device.h>
#include "drmP.h"
#include "drm.h"
#include "i915_drm.h"
@@ -66,6 +67,12 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
i915_save_state(dev);
+ /* If KMS is active, we do the leavevt stuff here */
+ if (drm_core_check_feature(dev, DRIVER_MODESET) && i915_gem_idle(dev)) {
+ dev_err(&dev->pdev->dev, "GEM idle failed, aborting suspend\n");
+ return -EBUSY;
+ }
+
intel_opregion_free(dev);
if (state.event == PM_EVENT_SUSPEND) {
@@ -79,6 +86,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
static int i915_resume(struct drm_device *dev)
{
+ struct drm_i915_private *dev_priv = dev->dev_private;
+ int ret = 0;
+
pci_set_power_state(dev->pdev, PCI_D0);
pci_restore_state(dev->pdev);
if (pci_enable_device(dev->pdev))
@@ -89,11 +99,24 @@ static int i915_resume(struct drm_device *dev)
intel_opregion_init(dev);
- return 0;
+ /* KMS EnterVT equivalent */
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+ mutex_lock(&dev->struct_mutex);
+ dev_priv->mm.suspended = 0;
+
+ ret = i915_gem_init_ringbuffer(dev);
+ if (ret != 0)
+ ret = -1;
+ mutex_unlock(&dev->struct_mutex);
+ }
+
+ return ret;
}
static struct vm_operations_struct i915_gem_vm_ops = {
.fault = i915_gem_fault,
+ .open = drm_gem_vm_open,
+ .close = drm_gem_vm_close,
};
static struct drm_driver driver = {
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7325363164f8..17fa40858d26 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -184,6 +184,8 @@ typedef struct drm_i915_private {
unsigned int lvds_dither:1;
unsigned int lvds_vbt:1;
unsigned int int_crt_support:1;
+ unsigned int lvds_use_ssc:1;
+ int lvds_ssc_freq;
struct drm_i915_fence_reg fence_regs[16]; /* assume 965 */
int fence_reg_start; /* 4 if userland hasn't ioctl'd us yet */
@@ -616,6 +618,7 @@ int i915_gem_init_ringbuffer(struct drm_device *dev);
void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
int i915_gem_do_init(struct drm_device *dev, unsigned long start,
unsigned long end);
+int i915_gem_idle(struct drm_device *dev);
int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
int i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj,
int write);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 818576654092..25b337438ca7 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -34,10 +34,6 @@
#define I915_GEM_GPU_DOMAINS (~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
-static void
-i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
- uint32_t read_domains,
- uint32_t write_domain);
static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
@@ -607,8 +603,6 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
case -EAGAIN:
return VM_FAULT_OOM;
case -EFAULT:
- case -EBUSY:
- DRM_ERROR("can't insert pfn?? fault or busy...\n");
return VM_FAULT_SIGBUS;
default:
return VM_FAULT_NOPAGE;
@@ -684,6 +678,30 @@ out_free_list:
return ret;
}
+static void
+i915_gem_free_mmap_offset(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ struct drm_gem_mm *mm = dev->mm_private;
+ struct drm_map_list *list;
+
+ list = &obj->map_list;
+ drm_ht_remove_item(&mm->offset_hash, &list->hash);
+
+ if (list->file_offset_node) {
+ drm_mm_put_block(list->file_offset_node);
+ list->file_offset_node = NULL;
+ }
+
+ if (list->map) {
+ drm_free(list->map, sizeof(struct drm_map), DRM_MEM_DRIVER);
+ list->map = NULL;
+ }
+
+ obj_priv->mmap_offset = 0;
+}
+
/**
* i915_gem_get_gtt_alignment - return required GTT alignment for an object
* @obj: object to check
@@ -758,8 +776,11 @@ i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
if (!obj_priv->mmap_offset) {
ret = i915_gem_create_mmap_offset(obj);
- if (ret)
+ if (ret) {
+ drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
return ret;
+ }
}
args->offset = obj_priv->mmap_offset;
@@ -1996,30 +2017,28 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
* drm_agp_chipset_flush
*/
static void
-i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
- uint32_t read_domains,
- uint32_t write_domain)
+i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
uint32_t invalidate_domains = 0;
uint32_t flush_domains = 0;
- BUG_ON(read_domains & I915_GEM_DOMAIN_CPU);
- BUG_ON(write_domain == I915_GEM_DOMAIN_CPU);
+ BUG_ON(obj->pending_read_domains & I915_GEM_DOMAIN_CPU);
+ BUG_ON(obj->pending_write_domain == I915_GEM_DOMAIN_CPU);
#if WATCH_BUF
DRM_INFO("%s: object %p read %08x -> %08x write %08x -> %08x\n",
__func__, obj,
- obj->read_domains, read_domains,
- obj->write_domain, write_domain);
+ obj->read_domains, obj->pending_read_domains,
+ obj->write_domain, obj->pending_write_domain);
#endif
/*
* If the object isn't moving to a new write domain,
* let the object stay in multiple read domains
*/
- if (write_domain == 0)
- read_domains |= obj->read_domains;
+ if (obj->pending_write_domain == 0)
+ obj->pending_read_domains |= obj->read_domains;
else
obj_priv->dirty = 1;
@@ -2029,15 +2048,17 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
* any read domains which differ from the old
* write domain
*/
- if (obj->write_domain && obj->write_domain != read_domains) {
+ if (obj->write_domain &&
+ obj->write_domain != obj->pending_read_domains) {
flush_domains |= obj->write_domain;
- invalidate_domains |= read_domains & ~obj->write_domain;
+ invalidate_domains |=
+ obj->pending_read_domains & ~obj->write_domain;
}
/*
* Invalidate any read caches which may have
* stale data. That is, any new read domains.
*/
- invalidate_domains |= read_domains & ~obj->read_domains;
+ invalidate_domains |= obj->pending_read_domains & ~obj->read_domains;
if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU) {
#if WATCH_BUF
DRM_INFO("%s: CPU domain flush %08x invalidate %08x\n",
@@ -2046,9 +2067,15 @@ i915_gem_object_set_to_gpu_domain(struct drm_gem_object *obj,
i915_gem_clflush_object(obj);
}
- if ((write_domain | flush_domains) != 0)
- obj->write_domain = write_domain;
- obj->read_domains = read_domains;
+ /* The actual obj->write_domain will be updated with
+ * pending_write_domain after we emit the accumulated flush for all
+ * of our domain changes in execbuffers (which clears objects'
+ * write_domains). So if we have a current write domain that we
+ * aren't changing, set pending_write_domain to that.
+ */
+ if (flush_domains == 0 && obj->pending_write_domain == 0)
+ obj->pending_write_domain = obj->write_domain;
+ obj->read_domains = obj->pending_read_domains;
dev->invalidate_domains |= invalidate_domains;
dev->flush_domains |= flush_domains;
@@ -2251,6 +2278,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
(int) reloc.offset,
reloc.read_domains,
reloc.write_domain);
+ drm_gem_object_unreference(target_obj);
+ i915_gem_object_unpin(obj);
return -EINVAL;
}
@@ -2480,13 +2509,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
if (dev_priv->mm.wedged) {
DRM_ERROR("Execbuf while wedged\n");
mutex_unlock(&dev->struct_mutex);
- return -EIO;
+ ret = -EIO;
+ goto pre_mutex_err;
}
if (dev_priv->mm.suspended) {
DRM_ERROR("Execbuf while VT-switched.\n");
mutex_unlock(&dev->struct_mutex);
- return -EBUSY;
+ ret = -EBUSY;
+ goto pre_mutex_err;
}
/* Look up object handles */
@@ -2554,9 +2585,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
struct drm_gem_object *obj = object_list[i];
/* Compute new gpu domains and update invalidate/flush */
- i915_gem_object_set_to_gpu_domain(obj,
- obj->pending_read_domains,
- obj->pending_write_domain);
+ i915_gem_object_set_to_gpu_domain(obj);
}
i915_verify_inactive(dev, __FILE__, __LINE__);
@@ -2575,6 +2604,12 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
(void)i915_add_request(dev, dev->flush_domains);
}
+ for (i = 0; i < args->buffer_count; i++) {
+ struct drm_gem_object *obj = object_list[i];
+
+ obj->write_domain = obj->pending_write_domain;
+ }
+
i915_verify_inactive(dev, __FILE__, __LINE__);
#if WATCH_COHERENCY
@@ -2632,15 +2667,6 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
i915_verify_inactive(dev, __FILE__, __LINE__);
- /* Copy the new buffer offsets back to the user's exec list. */
- ret = copy_to_user((struct drm_i915_relocation_entry __user *)
- (uintptr_t) args->buffers_ptr,
- exec_list,
- sizeof(*exec_list) * args->buffer_count);
- if (ret)
- DRM_ERROR("failed to copy %d exec entries "
- "back to user (%d)\n",
- args->buffer_count, ret);
err:
for (i = 0; i < pinned; i++)
i915_gem_object_unpin(object_list[i]);
@@ -2650,6 +2676,18 @@ err:
mutex_unlock(&dev->struct_mutex);
+ if (!ret) {
+ /* Copy the new buffer offsets back to the user's exec list. */
+ ret = copy_to_user((struct drm_i915_relocation_entry __user *)
+ (uintptr_t) args->buffers_ptr,
+ exec_list,
+ sizeof(*exec_list) * args->buffer_count);
+ if (ret)
+ DRM_ERROR("failed to copy %d exec entries "
+ "back to user (%d)\n",
+ args->buffer_count, ret);
+ }
+
pre_mutex_err:
drm_free(object_list, sizeof(*object_list) * args->buffer_count,
DRM_MEM_DRIVER);
@@ -2753,6 +2791,7 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
args->handle);
+ drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
@@ -2833,6 +2872,13 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
return -EBADF;
}
+ /* Update the active list for the hardware's current position.
+ * Otherwise this only updates on a delayed timer or when irqs are
+ * actually unmasked, and our working set ends up being larger than
+ * required.
+ */
+ i915_gem_retire_requests(dev);
+
obj_priv = obj->driver_private;
/* Don't count being on the flushing list against the object being
* done. Otherwise, a buffer left on the flushing list but not getting
@@ -2885,9 +2931,6 @@ int i915_gem_init_object(struct drm_gem_object *obj)
void i915_gem_free_object(struct drm_gem_object *obj)
{
struct drm_device *dev = obj->dev;
- struct drm_gem_mm *mm = dev->mm_private;
- struct drm_map_list *list;
- struct drm_map *map;
struct drm_i915_gem_object *obj_priv = obj->driver_private;
while (obj_priv->pin_count > 0)
@@ -2898,19 +2941,7 @@ void i915_gem_free_object(struct drm_gem_object *obj)
i915_gem_object_unbind(obj);
- list = &obj->map_list;
- drm_ht_remove_item(&mm->offset_hash, &list->hash);
-
- if (list->file_offset_node) {
- drm_mm_put_block(list->file_offset_node);
- list->file_offset_node = NULL;
- }
-
- map = list->map;
- if (map) {
- drm_free(map, sizeof(*map), DRM_MEM_DRIVER);
- list->map = NULL;
- }
+ i915_gem_free_mmap_offset(obj);
drm_free(obj_priv->page_cpu_valid, 1, DRM_MEM_DRIVER);
drm_free(obj->driver_private, 1, DRM_MEM_DRIVER);
@@ -2949,7 +2980,7 @@ i915_gem_evict_from_list(struct drm_device *dev, struct list_head *head)
return 0;
}
-static int
+int
i915_gem_idle(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = dev->dev_private;
@@ -3095,6 +3126,7 @@ i915_gem_init_hws(struct drm_device *dev)
if (dev_priv->hw_status_page == NULL) {
DRM_ERROR("Failed to map status page.\n");
memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+ i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
return -EINVAL;
}
@@ -3107,6 +3139,31 @@ i915_gem_init_hws(struct drm_device *dev)
return 0;
}
+static void
+i915_gem_cleanup_hws(struct drm_device *dev)
+{
+ drm_i915_private_t *dev_priv = dev->dev_private;
+ struct drm_gem_object *obj;
+ struct drm_i915_gem_object *obj_priv;
+
+ if (dev_priv->hws_obj == NULL)
+ return;
+
+ obj = dev_priv->hws_obj;
+ obj_priv = obj->driver_private;
+
+ kunmap(obj_priv->page_list[0]);
+ i915_gem_object_unpin(obj);
+ drm_gem_object_unreference(obj);
+ dev_priv->hws_obj = NULL;
+
+ memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
+ dev_priv->hw_status_page = NULL;
+
+ /* Write high address into HWS_PGA when disabling. */
+ I915_WRITE(HWS_PGA, 0x1ffff000);
+}
+
int
i915_gem_init_ringbuffer(struct drm_device *dev)
{
@@ -3124,6 +3181,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
obj = drm_gem_object_alloc(dev, 128 * 1024);
if (obj == NULL) {
DRM_ERROR("Failed to allocate ringbuffer\n");
+ i915_gem_cleanup_hws(dev);
return -ENOMEM;
}
obj_priv = obj->driver_private;
@@ -3131,6 +3189,7 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
ret = i915_gem_object_pin(obj, 4096);
if (ret != 0) {
drm_gem_object_unreference(obj);
+ i915_gem_cleanup_hws(dev);
return ret;
}
@@ -3148,7 +3207,9 @@ i915_gem_init_ringbuffer(struct drm_device *dev)
if (ring->map.handle == NULL) {
DRM_ERROR("Failed to map ringbuffer.\n");
memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
+ i915_gem_object_unpin(obj);
drm_gem_object_unreference(obj);
+ i915_gem_cleanup_hws(dev);
return -EINVAL;
}
ring->ring_obj = obj;
@@ -3228,20 +3289,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)
dev_priv->ring.ring_obj = NULL;
memset(&dev_priv->ring, 0, sizeof(dev_priv->ring));
- if (dev_priv->hws_obj != NULL) {
- struct drm_gem_object *obj = dev_priv->hws_obj;
- struct drm_i915_gem_object *obj_priv = obj->driver_private;
-
- kunmap(obj_priv->page_list[0]);
- i915_gem_object_unpin(obj);
- drm_gem_object_unreference(obj);
- dev_priv->hws_obj = NULL;
- memset(&dev_priv->hws_map, 0, sizeof(dev_priv->hws_map));
- dev_priv->hw_status_page = NULL;
-
- /* Write high address into HWS_PGA when disabling. */
- I915_WRITE(HWS_PGA, 0x1ffff000);
- }
+ i915_gem_cleanup_hws(dev);
}
int
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index fa1685cba840..7fb4191ef934 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -299,9 +299,8 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
}
obj_priv->stride = args->stride;
- mutex_unlock(&dev->struct_mutex);
-
drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
@@ -340,9 +339,8 @@ i915_gem_get_tiling(struct drm_device *dev, void *data,
DRM_ERROR("unknown tiling mode\n");
}
- mutex_unlock(&dev->struct_mutex);
-
drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
return 0;
}
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 4ca82a025525..65be30dccc77 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -135,6 +135,14 @@ parse_general_features(struct drm_i915_private *dev_priv,
if (general) {
dev_priv->int_tv_support = general->int_tv_support;
dev_priv->int_crt_support = general->int_crt_support;
+ dev_priv->lvds_use_ssc = general->enable_ssc;
+
+ if (dev_priv->lvds_use_ssc) {
+ if (IS_I855(dev_priv->dev))
+ dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
+ else
+ dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
+ }
}
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index bbdd72909a11..65b635ce28c8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -90,12 +90,12 @@ typedef struct {
#define I9XX_DOT_MAX 400000
#define I9XX_VCO_MIN 1400000
#define I9XX_VCO_MAX 2800000
-#define I9XX_N_MIN 3
-#define I9XX_N_MAX 8
+#define I9XX_N_MIN 1
+#define I9XX_N_MAX 6
#define I9XX_M_MIN 70
#define I9XX_M_MAX 120
#define I9XX_M1_MIN 10
-#define I9XX_M1_MAX 20
+#define I9XX_M1_MAX 22
#define I9XX_M2_MIN 5
#define I9XX_M2_MAX 9
#define I9XX_P_SDVO_DAC_MIN 5
@@ -189,9 +189,7 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc)
return limit;
}
-/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
-
-static void i8xx_clock(int refclk, intel_clock_t *clock)
+static void intel_clock(int refclk, intel_clock_t *clock)
{
clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
clock->p = clock->p1 * clock->p2;
@@ -199,25 +197,6 @@ static void i8xx_clock(int refclk, intel_clock_t *clock)
clock->dot = clock->vco / clock->p;
}
-/** Derive the pixel clock for the given refclk and divisors for 9xx chips. */
-
-static void i9xx_clock(int refclk, intel_clock_t *clock)
-{
- clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
- clock->p = clock->p1 * clock->p2;
- clock->vco = refclk * clock->m / (clock->n + 2);
- clock->dot = clock->vco / clock->p;
-}
-
-static void intel_clock(struct drm_device *dev, int refclk,
- intel_clock_t *clock)
-{
- if (IS_I9XX(dev))
- i9xx_clock (refclk, clock);
- else
- i8xx_clock (refclk, clock);
-}
-
/**
* Returns whether any output on the specified pipe is of the specified type
*/
@@ -238,7 +217,7 @@ bool intel_pipe_has_type (struct drm_crtc *crtc, int type)
return false;
}
-#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; }
+#define INTELPllInvalid(s) do { DRM_DEBUG(s); return false; } while (0)
/**
* Returns whether the given set of divisors are valid for a given refclk with
* the given connectors.
@@ -318,7 +297,7 @@ static bool intel_find_best_PLL(struct drm_crtc *crtc, int target,
clock.p1 <= limit->p1.max; clock.p1++) {
int this_err;
- intel_clock(dev, refclk, &clock);
+ intel_clock(refclk, &clock);
if (!intel_PLL_is_valid(crtc, &clock))
continue;
@@ -343,7 +322,7 @@ intel_wait_for_vblank(struct drm_device *dev)
udelay(20000);
}
-static void
+static int
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
{
@@ -361,11 +340,21 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
u32 dspcntr, alignment;
+ int ret;
/* no fb bound */
if (!crtc->fb) {
DRM_DEBUG("No FB bound\n");
- return;
+ return 0;
+ }
+
+ switch (pipe) {
+ case 0:
+ case 1:
+ break;
+ default:
+ DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
+ return -EINVAL;
}
intel_fb = to_intel_framebuffer(crtc->fb);
@@ -377,28 +366,30 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
alignment = 64 * 1024;
break;
case I915_TILING_X:
- if (IS_I9XX(dev))
- alignment = 1024 * 1024;
- else
- alignment = 512 * 1024;
+ /* pin() will align the object as required by fence */
+ alignment = 0;
break;
case I915_TILING_Y:
/* FIXME: Is this true? */
DRM_ERROR("Y tiled not allowed for scan out buffers\n");
- return;
+ return -EINVAL;
default:
BUG();
}
- if (i915_gem_object_pin(intel_fb->obj, alignment))
- return;
-
- i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
-
- Start = obj_priv->gtt_offset;
- Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+ mutex_lock(&dev->struct_mutex);
+ ret = i915_gem_object_pin(intel_fb->obj, alignment);
+ if (ret != 0) {
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
- I915_WRITE(dspstride, crtc->fb->pitch);
+ ret = i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
+ if (ret != 0) {
+ i915_gem_object_unpin(intel_fb->obj);
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
dspcntr = I915_READ(dspcntr_reg);
/* Mask out pixel format bits in case we change it */
@@ -419,11 +410,17 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
break;
default:
DRM_ERROR("Unknown color depth\n");
- return;
+ i915_gem_object_unpin(intel_fb->obj);
+ mutex_unlock(&dev->struct_mutex);
+ return -EINVAL;
}
I915_WRITE(dspcntr_reg, dspcntr);
+ Start = obj_priv->gtt_offset;
+ Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
+
DRM_DEBUG("Writing base %08lX %08lX %d %d\n", Start, Offset, x, y);
+ I915_WRITE(dspstride, crtc->fb->pitch);
if (IS_I965G(dev)) {
I915_WRITE(dspbase, Offset);
I915_READ(dspbase);
@@ -440,27 +437,24 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
intel_fb = to_intel_framebuffer(old_fb);
i915_gem_object_unpin(intel_fb->obj);
}
+ mutex_unlock(&dev->struct_mutex);
if (!dev->primary->master)
- return;
+ return 0;
master_priv = dev->primary->master->driver_priv;
if (!master_priv->sarea_priv)
- return;
+ return 0;
- switch (pipe) {
- case 0:
- master_priv->sarea_priv->pipeA_x = x;
- master_priv->sarea_priv->pipeA_y = y;
- break;
- case 1:
+ if (pipe) {
master_priv->sarea_priv->pipeB_x = x;
master_priv->sarea_priv->pipeB_y = y;
- break;
- default:
- DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
- break;
+ } else {
+ master_priv->sarea_priv->pipeA_x = x;
+ master_priv->sarea_priv->pipeA_y = y;
}
+
+ return 0;
}
@@ -708,11 +702,11 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
return 1;
}
-static void intel_crtc_mode_set(struct drm_crtc *crtc,
- struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode,
- int x, int y,
- struct drm_framebuffer *old_fb)
+static int intel_crtc_mode_set(struct drm_crtc *crtc,
+ struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode,
+ int x, int y,
+ struct drm_framebuffer *old_fb)
{
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -732,13 +726,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
- int refclk;
+ int refclk, num_outputs = 0;
intel_clock_t clock;
u32 dpll = 0, fp = 0, dspcntr, pipeconf;
bool ok, is_sdvo = false, is_dvo = false;
bool is_crt = false, is_lvds = false, is_tv = false;
struct drm_mode_config *mode_config = &dev->mode_config;
struct drm_connector *connector;
+ int ret;
drm_vblank_pre_modeset(dev, pipe);
@@ -768,9 +763,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
is_crt = true;
break;
}
+
+ num_outputs++;
}
- if (IS_I9XX(dev)) {
+ if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2) {
+ refclk = dev_priv->lvds_ssc_freq * 1000;
+ DRM_DEBUG("using SSC reference clock of %d MHz\n", refclk / 1000);
+ } else if (IS_I9XX(dev)) {
refclk = 96000;
} else {
refclk = 48000;
@@ -779,7 +779,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
ok = intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, &clock);
if (!ok) {
DRM_ERROR("Couldn't find PLL settings for mode!\n");
- return;
+ return -EINVAL;
}
fp = clock.n << 16 | clock.m1 << 8 | clock.m2;
@@ -829,11 +829,14 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
}
}
- if (is_tv) {
+ if (is_sdvo && is_tv)
+ dpll |= PLL_REF_INPUT_TVCLKINBC;
+ else if (is_tv)
/* XXX: just matching BIOS for now */
-/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
+ /* dpll |= PLL_REF_INPUT_TVCLKINBC; */
dpll |= 3;
- }
+ else if (is_lvds && dev_priv->lvds_use_ssc && num_outputs < 2)
+ dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN;
else
dpll |= PLL_REF_INPUT_DREFCLK;
@@ -950,9 +953,13 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
I915_WRITE(dspcntr_reg, dspcntr);
/* Flush the plane changes */
- intel_pipe_set_base(crtc, x, y, old_fb);
+ ret = intel_pipe_set_base(crtc, x, y, old_fb);
+ if (ret != 0)
+ return ret;
drm_vblank_post_modeset(dev, pipe);
+
+ return 0;
}
/** Loads the palette/gamma unit for the CRTC with the prepared values */
@@ -1001,6 +1008,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
temp = CURSOR_MODE_DISABLE;
addr = 0;
bo = NULL;
+ mutex_lock(&dev->struct_mutex);
goto finish;
}
@@ -1023,18 +1031,19 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
}
/* we only need to pin inside GTT if cursor is non-phy */
+ mutex_lock(&dev->struct_mutex);
if (!dev_priv->cursor_needs_physical) {
ret = i915_gem_object_pin(bo, PAGE_SIZE);
if (ret) {
DRM_ERROR("failed to pin cursor bo\n");
- goto fail;
+ goto fail_locked;
}
addr = obj_priv->gtt_offset;
} else {
ret = i915_gem_attach_phys_object(dev, bo, (pipe == 0) ? I915_GEM_PHYS_CURSOR_0 : I915_GEM_PHYS_CURSOR_1);
if (ret) {
DRM_ERROR("failed to attach phys object\n");
- goto fail;
+ goto fail_locked;
}
addr = obj_priv->phys_obj->handle->busaddr;
}
@@ -1054,10 +1063,9 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
i915_gem_detach_phys_object(dev, intel_crtc->cursor_bo);
} else
i915_gem_object_unpin(intel_crtc->cursor_bo);
- mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(intel_crtc->cursor_bo);
- mutex_unlock(&dev->struct_mutex);
}
+ mutex_unlock(&dev->struct_mutex);
intel_crtc->cursor_addr = addr;
intel_crtc->cursor_bo = bo;
@@ -1065,6 +1073,7 @@ static int intel_crtc_cursor_set(struct drm_crtc *crtc,
return 0;
fail:
mutex_lock(&dev->struct_mutex);
+fail_locked:
drm_gem_object_unreference(bo);
mutex_unlock(&dev->struct_mutex);
return ret;
@@ -1292,7 +1301,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
}
/* XXX: Handle the 100Mhz refclk */
- i9xx_clock(96000, &clock);
+ intel_clock(96000, &clock);
} else {
bool is_lvds = (pipe == 1) && (I915_READ(LVDS) & LVDS_PORT_EN);
@@ -1304,9 +1313,9 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
if ((dpll & PLL_REF_INPUT_MASK) ==
PLLB_REF_INPUT_SPREADSPECTRUMIN) {
/* XXX: might not be 66MHz */
- i8xx_clock(66000, &clock);
+ intel_clock(66000, &clock);
} else
- i8xx_clock(48000, &clock);
+ intel_clock(48000, &clock);
} else {
if (dpll & PLL_P1_DIVIDE_BY_TWO)
clock.p1 = 2;
@@ -1319,7 +1328,7 @@ static int intel_crtc_clock_get(struct drm_device *dev, struct drm_crtc *crtc)
else
clock.p2 = 2;
- i8xx_clock(48000, &clock);
+ intel_clock(48000, &clock);
}
}
@@ -1598,7 +1607,9 @@ intel_user_framebuffer_create(struct drm_device *dev,
ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj);
if (ret) {
+ mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
return NULL;
}
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c
index afd1217b8a02..b7f0ebe9f810 100644
--- a/drivers/gpu/drm/i915/intel_fb.c
+++ b/drivers/gpu/drm/i915/intel_fb.c
@@ -473,7 +473,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo);
if (ret) {
DRM_ERROR("failed to allocate fb.\n");
- goto out_unref;
+ goto out_unpin;
}
list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list);
@@ -484,7 +484,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
info = framebuffer_alloc(sizeof(struct intelfb_par), device);
if (!info) {
ret = -ENOMEM;
- goto out_unref;
+ goto out_unpin;
}
par = info->par;
@@ -513,7 +513,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
size);
if (!info->screen_base) {
ret = -ENOSPC;
- goto out_unref;
+ goto out_unpin;
}
info->screen_size = size;
@@ -608,6 +608,8 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width,
mutex_unlock(&dev->struct_mutex);
return 0;
+out_unpin:
+ i915_gem_object_unpin(fbo);
out_unref:
drm_gem_object_unreference(fbo);
mutex_unlock(&dev->struct_mutex);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 6d4f91265354..0d211af98854 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -481,8 +481,6 @@ void intel_lvds_init(struct drm_device *dev)
if (dev_priv->panel_fixed_mode) {
dev_priv->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED;
- drm_mode_probed_add(connector,
- dev_priv->panel_fixed_mode);
goto out;
}
}
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index a30508b639ba..fbe6f3931b1b 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -193,7 +193,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr,
#define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd}
/** Mapping of command numbers to names, for debug output */
-const static struct _sdvo_cmd_name {
+static const struct _sdvo_cmd_name {
u8 cmd;
char *name;
} sdvo_cmd_names[] = {
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index fbb35dc56f5c..56485d67369b 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -411,7 +411,7 @@ struct tv_mode {
* These values account for -1s required.
*/
-const static struct tv_mode tv_modes[] = {
+static const struct tv_mode tv_modes[] = {
{
.name = "NTSC-M",
.clock = 107520,
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c
index df4cf97e5d97..92965dbb3c14 100644
--- a/drivers/gpu/drm/radeon/radeon_cp.c
+++ b/drivers/gpu/drm/radeon/radeon_cp.c
@@ -557,8 +557,10 @@ static int radeon_do_engine_reset(struct drm_device * dev)
}
static void radeon_cp_init_ring_buffer(struct drm_device * dev,
- drm_radeon_private_t * dev_priv)
+ drm_radeon_private_t *dev_priv,
+ struct drm_file *file_priv)
{
+ struct drm_radeon_master_private *master_priv;
u32 ring_start, cur_read_ptr;
u32 tmp;
@@ -677,6 +679,14 @@ static void radeon_cp_init_ring_buffer(struct drm_device * dev,
dev_priv->scratch[2] = 0;
RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0);
+ /* reset sarea copies of these */
+ master_priv = file_priv->master->driver_priv;
+ if (master_priv->sarea_priv) {
+ master_priv->sarea_priv->last_frame = 0;
+ master_priv->sarea_priv->last_dispatch = 0;
+ master_priv->sarea_priv->last_clear = 0;
+ }
+
radeon_do_wait_for_idle(dev_priv);
/* Sync everything up */
@@ -1215,7 +1225,7 @@ static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
}
radeon_cp_load_microcode(dev_priv);
- radeon_cp_init_ring_buffer(dev, dev_priv);
+ radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
dev_priv->last_buf = 0;
@@ -1281,7 +1291,7 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
*
* Charl P. Botha <http://cpbotha.net>
*/
-static int radeon_do_resume_cp(struct drm_device * dev)
+static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
{
drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1304,7 +1314,7 @@ static int radeon_do_resume_cp(struct drm_device * dev)
}
radeon_cp_load_microcode(dev_priv);
- radeon_cp_init_ring_buffer(dev, dev_priv);
+ radeon_cp_init_ring_buffer(dev, dev_priv, file_priv);
radeon_do_engine_reset(dev);
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
@@ -1479,8 +1489,7 @@ int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_pri
*/
int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv)
{
-
- return radeon_do_resume_cp(dev);
+ return radeon_do_resume_cp(dev, file_priv);
}
int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv)
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 6cad69ed21c5..1cc967448f4d 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -1300,7 +1300,13 @@ static const struct hid_device_id hid_blacklist[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SUNPLUS, USB_DEVICE_ID_SUNPLUS_WDESKTOP) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, 0x030c) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) },
@@ -1605,6 +1611,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD3) },
@@ -1612,10 +1619,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD5) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY1) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TENX, USB_DEVICE_ID_TENX_IBUDDY2) },
- { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb300) },
- { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb304) },
- { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb651) },
- { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb654) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
@@ -1626,8 +1629,6 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) },
{ HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) },
- { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) },
{ }
};
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index e899f510ebeb..88511970508d 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -348,6 +348,9 @@
#define USB_VENDOR_ID_PLAYDOTCOM 0x0b43
#define USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII 0x0003
+#define USB_VENDOR_ID_POWERCOM 0x0d9f
+#define USB_DEVICE_ID_POWERCOM_UPS 0x0002
+
#define USB_VENDOR_ID_SAITEK 0x06a3
#define USB_DEVICE_ID_SAITEK_RUMBLEPAD 0xff17
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 732449628971..02b19db5442e 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -267,8 +267,10 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
default:
{
struct hid_device *hid = dev->hid;
- if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
- return -EINVAL;
+ if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) {
+ ret = -EINVAL;
+ break;
+ }
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
int len;
@@ -277,8 +279,9 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
len = strlen(hid->name) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
- return copy_to_user(user_arg, hid->name, len) ?
+ ret = copy_to_user(user_arg, hid->name, len) ?
-EFAULT : len;
+ break;
}
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
@@ -288,12 +291,13 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd,
len = strlen(hid->phys) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
- return copy_to_user(user_arg, hid->phys, len) ?
+ ret = copy_to_user(user_arg, hid->phys, len) ?
-EFAULT : len;
+ break;
}
}
- ret = -ENOTTY;
+ ret = -ENOTTY;
}
unlock_kernel();
return ret;
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c
index 609cafff86bc..5f81ddf71508 100644
--- a/drivers/hwmon/f71882fg.c
+++ b/drivers/hwmon/f71882fg.c
@@ -1872,7 +1872,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
devid = superio_inw(sioaddr, SIO_REG_MANID);
if (devid != SIO_FINTEK_ID) {
- printk(KERN_INFO DRVNAME ": Not a Fintek device\n");
+ pr_debug(DRVNAME ": Not a Fintek device\n");
goto exit;
}
@@ -1932,7 +1932,7 @@ static int __init f71882fg_device_add(unsigned short address,
res.name = f71882fg_pdev->name;
err = acpi_check_resource_conflict(&res);
if (err)
- return err;
+ goto exit_device_put;
err = platform_device_add_resources(f71882fg_pdev, &res, 1);
if (err) {
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index abf4dfc8ec22..29c83b5b9697 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -166,6 +166,18 @@ static struct axis_conversion lis3lv02d_axis_xy_swap_yz_inverted = {2, -1, -3};
}, \
.driver_data = &lis3lv02d_axis_##_axis \
}
+
+#define AXIS_DMI_MATCH2(_ident, _class1, _name1, \
+ _class2, _name2, \
+ _axis) { \
+ .ident = _ident, \
+ .callback = lis3lv02d_dmi_matched, \
+ .matches = { \
+ DMI_MATCH(DMI_##_class1, _name1), \
+ DMI_MATCH(DMI_##_class2, _name2), \
+ }, \
+ .driver_data = &lis3lv02d_axis_##_axis \
+}
static struct dmi_system_id lis3lv02d_dmi_ids[] = {
/* product names are truncated to match all kinds of a same model */
AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
@@ -179,6 +191,16 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
AXIS_DMI_MATCH("NC671xx", "HP Compaq 671", xy_swap_yz_inverted),
+ /* Intel-based HP Pavilion dv5 */
+ AXIS_DMI_MATCH2("HPDV5_I",
+ PRODUCT_NAME, "HP Pavilion dv5",
+ BOARD_NAME, "3603",
+ x_inverted),
+ /* AMD-based HP Pavilion dv5 */
+ AXIS_DMI_MATCH2("HPDV5_A",
+ PRODUCT_NAME, "HP Pavilion dv5",
+ BOARD_NAME, "3600",
+ y_inverted),
{ NULL, }
/* Laptop models without axis info (yet):
* "NC6910" "HP Compaq 6910"
@@ -213,9 +235,49 @@ static struct delayed_led_classdev hpled_led = {
.set_brightness = hpled_set,
};
+static acpi_status
+lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
+{
+ if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
+ struct acpi_resource_extended_irq *irq;
+ u32 *device_irq = context;
+
+ irq = &resource->data.extended_irq;
+ *device_irq = irq->interrupts[0];
+ }
+
+ return AE_OK;
+}
+
+static void lis3lv02d_enum_resources(struct acpi_device *device)
+{
+ acpi_status status;
+
+ status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+ lis3lv02d_get_resource, &adev.irq);
+ if (ACPI_FAILURE(status))
+ printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
+}
+
+static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
+{
+ u8 lo, hi;
+
+ adev.read(handle, reg - 1, &lo);
+ adev.read(handle, reg, &hi);
+ /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
+ return (s16)((hi << 8) | lo);
+}
+
+static s16 lis3lv02d_read_8(acpi_handle handle, int reg)
+{
+ s8 lo;
+ adev.read(handle, reg, &lo);
+ return lo;
+}
+
static int lis3lv02d_add(struct acpi_device *device)
{
- u8 val;
int ret;
if (!device)
@@ -229,10 +291,22 @@ static int lis3lv02d_add(struct acpi_device *device)
strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
device->driver_data = &adev;
- lis3lv02d_acpi_read(device->handle, WHO_AM_I, &val);
- if ((val != LIS3LV02DL_ID) && (val != LIS302DL_ID)) {
+ lis3lv02d_acpi_read(device->handle, WHO_AM_I, &adev.whoami);
+ switch (adev.whoami) {
+ case LIS_DOUBLE_ID:
+ printk(KERN_INFO DRIVER_NAME ": 2-byte sensor found\n");
+ adev.read_data = lis3lv02d_read_16;
+ adev.mdps_max_val = 2048;
+ break;
+ case LIS_SINGLE_ID:
+ printk(KERN_INFO DRIVER_NAME ": 1-byte sensor found\n");
+ adev.read_data = lis3lv02d_read_8;
+ adev.mdps_max_val = 128;
+ break;
+ default:
printk(KERN_ERR DRIVER_NAME
- ": Accelerometer chip not LIS3LV02D{L,Q}\n");
+ ": unknown sensor type 0x%X\n", adev.whoami);
+ return -EINVAL;
}
/* If possible use a "standard" axes order */
@@ -247,6 +321,9 @@ static int lis3lv02d_add(struct acpi_device *device)
if (ret)
return ret;
+ /* obtain IRQ number of our device from ACPI */
+ lis3lv02d_enum_resources(adev.device);
+
ret = lis3lv02d_init_device(&adev);
if (ret) {
flush_work(&hpled_led.work);
diff --git a/drivers/hwmon/lis3lv02d.c b/drivers/hwmon/lis3lv02d.c
index 219d2d0d5a62..8bb2158f0453 100644
--- a/drivers/hwmon/lis3lv02d.c
+++ b/drivers/hwmon/lis3lv02d.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2007-2008 Yan Burman
* Copyright (C) 2008 Eric Piel
- * Copyright (C) 2008 Pavel Machek
+ * Copyright (C) 2008-2009 Pavel Machek
*
* 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
@@ -35,6 +35,7 @@
#include <linux/poll.h>
#include <linux/freezer.h>
#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
#include <acpi/acpi_drivers.h>
#include <asm/atomic.h>
#include "lis3lv02d.h"
@@ -52,24 +53,14 @@
* joystick.
*/
-/* Maximum value our axis may get for the input device (signed 12 bits) */
-#define MDPS_MAX_VAL 2048
+struct acpi_lis3lv02d adev = {
+ .misc_wait = __WAIT_QUEUE_HEAD_INITIALIZER(adev.misc_wait),
+};
-struct acpi_lis3lv02d adev;
EXPORT_SYMBOL_GPL(adev);
static int lis3lv02d_add_fs(struct acpi_device *device);
-static s16 lis3lv02d_read_16(acpi_handle handle, int reg)
-{
- u8 lo, hi;
-
- adev.read(handle, reg, &lo);
- adev.read(handle, reg + 1, &hi);
- /* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
- return (s16)((hi << 8) | lo);
-}
-
/**
* lis3lv02d_get_axis - For the given axis, give the value converted
* @axis: 1,2,3 - can also be negative
@@ -98,9 +89,9 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
{
int position[3];
- position[0] = lis3lv02d_read_16(handle, OUTX_L);
- position[1] = lis3lv02d_read_16(handle, OUTY_L);
- position[2] = lis3lv02d_read_16(handle, OUTZ_L);
+ position[0] = adev.read_data(handle, OUTX);
+ position[1] = adev.read_data(handle, OUTY);
+ position[2] = adev.read_data(handle, OUTZ);
*x = lis3lv02d_get_axis(adev.ac.x, position);
*y = lis3lv02d_get_axis(adev.ac.y, position);
@@ -110,26 +101,13 @@ static void lis3lv02d_get_xyz(acpi_handle handle, int *x, int *y, int *z)
void lis3lv02d_poweroff(acpi_handle handle)
{
adev.is_on = 0;
- /* disable X,Y,Z axis and power down */
- adev.write(handle, CTRL_REG1, 0x00);
}
EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
void lis3lv02d_poweron(acpi_handle handle)
{
- u8 val;
-
adev.is_on = 1;
adev.init(handle);
- adev.write(handle, FF_WU_CFG, 0);
- /*
- * BDU: LSB and MSB values are not updated until both have been read.
- * So the value read will always be correct.
- * IEN: Interrupt for free-fall and DD, not for data-ready.
- */
- adev.read(handle, CTRL_REG2, &val);
- val |= CTRL2_BDU | CTRL2_IEN;
- adev.write(handle, CTRL_REG2, val);
}
EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
@@ -162,6 +140,140 @@ static void lis3lv02d_decrease_use(struct acpi_lis3lv02d *dev)
mutex_unlock(&dev->lock);
}
+static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
+{
+ /*
+ * Be careful: on some HP laptops the bios force DD when on battery and
+ * the lid is closed. This leads to interrupts as soon as a little move
+ * is done.
+ */
+ atomic_inc(&adev.count);
+
+ wake_up_interruptible(&adev.misc_wait);
+ kill_fasync(&adev.async_queue, SIGIO, POLL_IN);
+ return IRQ_HANDLED;
+}
+
+static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
+{
+ int ret;
+
+ if (test_and_set_bit(0, &adev.misc_opened))
+ return -EBUSY; /* already open */
+
+ atomic_set(&adev.count, 0);
+
+ /*
+ * The sensor can generate interrupts for free-fall and direction
+ * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
+ * the things simple and _fast_ we activate it only for free-fall, so
+ * no need to read register (very slow with ACPI). For the same reason,
+ * we forbid shared interrupts.
+ *
+ * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
+ * io-apic is not configurable (and generates a warning) but I keep it
+ * in case of support for other hardware.
+ */
+ ret = request_irq(adev.irq, lis302dl_interrupt, IRQF_TRIGGER_RISING,
+ DRIVER_NAME, &adev);
+
+ if (ret) {
+ clear_bit(0, &adev.misc_opened);
+ printk(KERN_ERR DRIVER_NAME ": IRQ%d allocation failed\n", adev.irq);
+ return -EBUSY;
+ }
+ lis3lv02d_increase_use(&adev);
+ printk("lis3: registered interrupt %d\n", adev.irq);
+ return 0;
+}
+
+static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
+{
+ fasync_helper(-1, file, 0, &adev.async_queue);
+ lis3lv02d_decrease_use(&adev);
+ free_irq(adev.irq, &adev);
+ clear_bit(0, &adev.misc_opened); /* release the device */
+ return 0;
+}
+
+static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
+ size_t count, loff_t *pos)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ u32 data;
+ unsigned char byte_data;
+ ssize_t retval = 1;
+
+ if (count < 1)
+ return -EINVAL;
+
+ add_wait_queue(&adev.misc_wait, &wait);
+ while (true) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ data = atomic_xchg(&adev.count, 0);
+ if (data)
+ break;
+
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto out;
+ }
+
+ if (signal_pending(current)) {
+ retval = -ERESTARTSYS;
+ goto out;
+ }
+
+ schedule();
+ }
+
+ if (data < 255)
+ byte_data = data;
+ else
+ byte_data = 255;
+
+ /* make sure we are not going into copy_to_user() with
+ * TASK_INTERRUPTIBLE state */
+ set_current_state(TASK_RUNNING);
+ if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
+ retval = -EFAULT;
+
+out:
+ __set_current_state(TASK_RUNNING);
+ remove_wait_queue(&adev.misc_wait, &wait);
+
+ return retval;
+}
+
+static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
+{
+ poll_wait(file, &adev.misc_wait, wait);
+ if (atomic_read(&adev.count))
+ return POLLIN | POLLRDNORM;
+ return 0;
+}
+
+static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
+{
+ return fasync_helper(fd, file, on, &adev.async_queue);
+}
+
+static const struct file_operations lis3lv02d_misc_fops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .read = lis3lv02d_misc_read,
+ .open = lis3lv02d_misc_open,
+ .release = lis3lv02d_misc_release,
+ .poll = lis3lv02d_misc_poll,
+ .fasync = lis3lv02d_misc_fasync,
+};
+
+static struct miscdevice lis3lv02d_misc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "freefall",
+ .fops = &lis3lv02d_misc_fops,
+};
+
/**
* lis3lv02d_joystick_kthread - Kthread polling function
* @data: unused - here to conform to threadfn prototype
@@ -203,7 +315,6 @@ static void lis3lv02d_joystick_close(struct input_dev *input)
lis3lv02d_decrease_use(&adev);
}
-
static inline void lis3lv02d_calibrate_joystick(void)
{
lis3lv02d_get_xyz(adev.device->handle, &adev.xcalib, &adev.ycalib, &adev.zcalib);
@@ -231,9 +342,9 @@ int lis3lv02d_joystick_enable(void)
adev.idev->close = lis3lv02d_joystick_close;
set_bit(EV_ABS, adev.idev->evbit);
- input_set_abs_params(adev.idev, ABS_X, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
- input_set_abs_params(adev.idev, ABS_Y, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
- input_set_abs_params(adev.idev, ABS_Z, -MDPS_MAX_VAL, MDPS_MAX_VAL, 3, 3);
+ input_set_abs_params(adev.idev, ABS_X, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
+ input_set_abs_params(adev.idev, ABS_Y, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
+ input_set_abs_params(adev.idev, ABS_Z, -adev.mdps_max_val, adev.mdps_max_val, 3, 3);
err = input_register_device(adev.idev);
if (err) {
@@ -250,6 +361,7 @@ void lis3lv02d_joystick_disable(void)
if (!adev.idev)
return;
+ misc_deregister(&lis3lv02d_misc_device);
input_unregister_device(adev.idev);
adev.idev = NULL;
}
@@ -268,6 +380,19 @@ int lis3lv02d_init_device(struct acpi_lis3lv02d *dev)
if (lis3lv02d_joystick_enable())
printk(KERN_ERR DRIVER_NAME ": joystick initialization failed\n");
+ printk("lis3_init_device: irq %d\n", dev->irq);
+
+ /* if we did not get an IRQ from ACPI - we have nothing more to do */
+ if (!dev->irq) {
+ printk(KERN_ERR DRIVER_NAME
+ ": No IRQ in ACPI. Disabling /dev/freefall\n");
+ goto out;
+ }
+
+ printk("lis3: registering device\n");
+ if (misc_register(&lis3lv02d_misc_device))
+ printk(KERN_ERR DRIVER_NAME ": misc_register failed\n");
+out:
lis3lv02d_decrease_use(dev);
return 0;
}
@@ -351,6 +476,6 @@ int lis3lv02d_remove_fs(void)
EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
-MODULE_AUTHOR("Yan Burman and Eric Piel");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/lis3lv02d.h b/drivers/hwmon/lis3lv02d.h
index 223f1c0763bb..75972bf372ff 100644
--- a/drivers/hwmon/lis3lv02d.h
+++ b/drivers/hwmon/lis3lv02d.h
@@ -22,12 +22,15 @@
/*
* The actual chip is STMicroelectronics LIS3LV02DL or LIS3LV02DQ that seems to
* be connected via SPI. There exists also several similar chips (such as LIS302DL or
- * LIS3L02DQ) but not in the HP laptops and they have slightly different registers.
+ * LIS3L02DQ) and they have slightly different registers, but we can provide a
+ * common interface for all of them.
* They can also be connected via I²C.
*/
-#define LIS3LV02DL_ID 0x3A /* Also the LIS3LV02DQ */
-#define LIS302DL_ID 0x3B /* Also the LIS202DL! */
+/* 2-byte registers */
+#define LIS_DOUBLE_ID 0x3A /* LIS3LV02D[LQ] */
+/* 1-byte registers */
+#define LIS_SINGLE_ID 0x3B /* LIS[32]02DL and others */
enum lis3lv02d_reg {
WHO_AM_I = 0x0F,
@@ -44,10 +47,13 @@ enum lis3lv02d_reg {
STATUS_REG = 0x27,
OUTX_L = 0x28,
OUTX_H = 0x29,
+ OUTX = 0x29,
OUTY_L = 0x2A,
OUTY_H = 0x2B,
+ OUTY = 0x2B,
OUTZ_L = 0x2C,
OUTZ_H = 0x2D,
+ OUTZ = 0x2D,
FF_WU_CFG = 0x30,
FF_WU_SRC = 0x31,
FF_WU_ACK = 0x32,
@@ -159,6 +165,10 @@ struct acpi_lis3lv02d {
acpi_status (*write) (acpi_handle handle, int reg, u8 val);
acpi_status (*read) (acpi_handle handle, int reg, u8 *ret);
+ u8 whoami; /* 3Ah: 2-byte registries, 3Bh: 1-byte registries */
+ s16 (*read_data) (acpi_handle handle, int reg);
+ int mdps_max_val;
+
struct input_dev *idev; /* input device */
struct task_struct *kthread; /* kthread for input */
struct mutex lock;
@@ -170,6 +180,11 @@ struct acpi_lis3lv02d {
unsigned char is_on; /* whether the device is on or off */
unsigned char usage; /* usage counter */
struct axis_conversion ac; /* hw -> logical axis */
+
+ u32 irq; /* IRQ number */
+ struct fasync_struct *async_queue; /* queue for the misc device */
+ wait_queue_head_t misc_wait; /* Wait queue for the misc device */
+ unsigned long misc_opened; /* bit0: whether the device is open */
};
int lis3lv02d_init_device(struct acpi_lis3lv02d *dev);
diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c
index b0ce37852281..73f77a9b8b18 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -1262,7 +1262,7 @@ static int __init vt1211_device_add(unsigned short address)
res.name = pdev->name;
err = acpi_check_resource_conflict(&res);
if (err)
- goto EXIT;
+ goto EXIT_DEV_PUT;
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index cb808d015361..feae743ba991 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -1548,7 +1548,7 @@ static int __init sensors_w83627ehf_init(void)
err = acpi_check_resource_conflict(&res);
if (err)
- goto exit;
+ goto exit_device_put;
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
diff --git a/drivers/lguest/Kconfig b/drivers/lguest/Kconfig
index 76f2b36881c3..a3d3cbab359a 100644
--- a/drivers/lguest/Kconfig
+++ b/drivers/lguest/Kconfig
@@ -1,6 +1,6 @@
config LGUEST
tristate "Linux hypervisor example code"
- depends on X86_32 && EXPERIMENTAL && !X86_PAE && FUTEX && !X86_VOYAGER
+ depends on X86_32 && EXPERIMENTAL && !X86_PAE && FUTEX
select HVC_DRIVER
---help---
This is a very simple module which allows you to run
diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c
index a34338567a2a..f14813be4eff 100644
--- a/drivers/md/dm-io.c
+++ b/drivers/md/dm-io.c
@@ -328,7 +328,7 @@ static void dispatch_io(int rw, unsigned int num_regions,
struct dpages old_pages = *dp;
if (sync)
- rw |= (1 << BIO_RW_SYNC);
+ rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
/*
* For multiple regions we need to be careful to rewind
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 3073618269ea..0a225da21272 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -344,7 +344,7 @@ static int run_io_job(struct kcopyd_job *job)
{
int r;
struct dm_io_request io_req = {
- .bi_rw = job->rw | (1 << BIO_RW_SYNC),
+ .bi_rw = job->rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG),
.mem.type = DM_IO_PAGE_LIST,
.mem.ptr.pl = job->pages,
.mem.offset = job->offset,
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 4495104f6c9f..03b4cd0a6344 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -474,7 +474,7 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev,
* causes ENOTSUPP, we allocate a spare bio...
*/
struct bio *bio = bio_alloc(GFP_NOIO, 1);
- int rw = (1<<BIO_RW) | (1<<BIO_RW_SYNC);
+ int rw = (1<<BIO_RW) | (1<<BIO_RW_SYNCIO) | (1<<BIO_RW_UNPLUG);
bio->bi_bdev = rdev->bdev;
bio->bi_sector = sector;
@@ -531,7 +531,7 @@ int sync_page_io(struct block_device *bdev, sector_t sector, int size,
struct completion event;
int ret;
- rw |= (1 << BIO_RW_SYNC);
+ rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
bio->bi_bdev = bdev;
bio->bi_sector = sector;
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
index de7adaf5fa5b..78412c9c424a 100644
--- a/drivers/media/common/tuners/tuner-simple.c
+++ b/drivers/media/common/tuners/tuner-simple.c
@@ -318,7 +318,6 @@ static int simple_std_setup(struct dvb_frontend *fe,
u8 *config, u8 *cb)
{
struct tuner_simple_priv *priv = fe->tuner_priv;
- u8 tuneraddr;
int rc;
/* tv norm specific stuff for multi-norm tuners */
@@ -387,6 +386,7 @@ static int simple_std_setup(struct dvb_frontend *fe,
case TUNER_PHILIPS_TUV1236D:
{
+ struct tuner_i2c_props i2c = priv->i2c_props;
/* 0x40 -> ATSC antenna input 1 */
/* 0x48 -> ATSC antenna input 2 */
/* 0x00 -> NTSC antenna input 1 */
@@ -398,17 +398,15 @@ static int simple_std_setup(struct dvb_frontend *fe,
buffer[1] = 0x04;
}
/* set to the correct mode (analog or digital) */
- tuneraddr = priv->i2c_props.addr;
- priv->i2c_props.addr = 0x0a;
- rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[0], 2);
+ i2c.addr = 0x0a;
+ rc = tuner_i2c_xfer_send(&i2c, &buffer[0], 2);
if (2 != rc)
tuner_warn("i2c i/o error: rc == %d "
"(should be 2)\n", rc);
- rc = tuner_i2c_xfer_send(&priv->i2c_props, &buffer[2], 2);
+ rc = tuner_i2c_xfer_send(&i2c, &buffer[2], 2);
if (2 != rc)
tuner_warn("i2c i/o error: rc == %d "
"(should be 2)\n", rc);
- priv->i2c_props.addr = tuneraddr;
break;
}
}
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 0c733c66a441..069d847ba887 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -364,16 +364,15 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
enum dmx_success success)
{
struct dmxdev_filter *dmxdevfilter = filter->priv;
- unsigned long flags;
int ret;
if (dmxdevfilter->buffer.error) {
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
- spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
+ spin_lock(&dmxdevfilter->dev->lock);
if (dmxdevfilter->state != DMXDEV_STATE_GO) {
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
return 0;
}
del_timer(&dmxdevfilter->timer);
@@ -392,7 +391,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
}
if (dmxdevfilter->params.sec.flags & DMX_ONESHOT)
dmxdevfilter->state = DMXDEV_STATE_DONE;
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&dmxdevfilter->buffer.queue);
return 0;
}
@@ -404,12 +403,11 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
{
struct dmxdev_filter *dmxdevfilter = feed->priv;
struct dvb_ringbuffer *buffer;
- unsigned long flags;
int ret;
- spin_lock_irqsave(&dmxdevfilter->dev->lock, flags);
+ spin_lock(&dmxdevfilter->dev->lock);
if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
return 0;
}
@@ -419,7 +417,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
else
buffer = &dmxdevfilter->dev->dvr_buffer;
if (buffer->error) {
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue);
return 0;
}
@@ -430,7 +428,7 @@ static int dvb_dmxdev_ts_callback(const u8 *buffer1, size_t buffer1_len,
dvb_ringbuffer_flush(buffer);
buffer->error = ret;
}
- spin_unlock_irqrestore(&dmxdevfilter->dev->lock, flags);
+ spin_unlock(&dmxdevfilter->dev->lock);
wake_up(&buffer->queue);
return 0;
}
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index a2c1fd5d2f67..e2eca0b1fe7c 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -399,9 +399,7 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
size_t count)
{
- unsigned long flags;
-
- spin_lock_irqsave(&demux->lock, flags);
+ spin_lock(&demux->lock);
while (count--) {
if (buf[0] == 0x47)
@@ -409,17 +407,16 @@ void dvb_dmx_swfilter_packets(struct dvb_demux *demux, const u8 *buf,
buf += 188;
}
- spin_unlock_irqrestore(&demux->lock, flags);
+ spin_unlock(&demux->lock);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
{
- unsigned long flags;
int p = 0, i, j;
- spin_lock_irqsave(&demux->lock, flags);
+ spin_lock(&demux->lock);
if (demux->tsbufp) {
i = demux->tsbufp;
@@ -452,18 +449,17 @@ void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
}
bailout:
- spin_unlock_irqrestore(&demux->lock, flags);
+ spin_unlock(&demux->lock);
}
EXPORT_SYMBOL(dvb_dmx_swfilter);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
{
- unsigned long flags;
int p = 0, i, j;
u8 tmppack[188];
- spin_lock_irqsave(&demux->lock, flags);
+ spin_lock(&demux->lock);
if (demux->tsbufp) {
i = demux->tsbufp;
@@ -504,7 +500,7 @@ void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf, size_t count)
}
bailout:
- spin_unlock_irqrestore(&demux->lock, flags);
+ spin_unlock(&demux->lock);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
diff --git a/drivers/media/radio/radio-si470x.c b/drivers/media/radio/radio-si470x.c
index 67cbce82cb91..4dfed6aa2dbc 100644
--- a/drivers/media/radio/radio-si470x.c
+++ b/drivers/media/radio/radio-si470x.c
@@ -98,11 +98,16 @@
* - blacklisted KWorld radio in hid-core.c and hid-ids.h
* 2008-12-03 Mark Lord <mlord@pobox.com>
* - add support for DealExtreme USB Radio
+ * 2009-01-31 Bob Ross <pigiron@gmx.com>
+ * - correction of stereo detection/setting
+ * - correction of signal strength indicator scaling
+ * 2009-01-31 Rick Bronson <rick@efn.org>
+ * Tobias Lorenz <tobias.lorenz@gmx.net>
+ * - add LED status output
*
* ToDo:
* - add firmware download/update support
* - RDS support: interrupt mode, instead of polling
- * - add LED status output (check if that's not already done in firmware)
*/
@@ -882,6 +887,30 @@ static int si470x_rds_on(struct si470x_device *radio)
/**************************************************************************
+ * General Driver Functions - LED_REPORT
+ **************************************************************************/
+
+/*
+ * si470x_set_led_state - sets the led state
+ */
+static int si470x_set_led_state(struct si470x_device *radio,
+ unsigned char led_state)
+{
+ unsigned char buf[LED_REPORT_SIZE];
+ int retval;
+
+ buf[0] = LED_REPORT;
+ buf[1] = LED_COMMAND;
+ buf[2] = led_state;
+
+ retval = si470x_set_report(radio, (void *) &buf, sizeof(buf));
+
+ return (retval < 0) ? -EINVAL : 0;
+}
+
+
+
+/**************************************************************************
* RDS Driver Functions
**************************************************************************/
@@ -1385,20 +1414,22 @@ static int si470x_vidioc_g_tuner(struct file *file, void *priv,
};
/* stereo indicator == stereo (instead of mono) */
- if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 1)
- tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
- else
+ if ((radio->registers[STATUSRSSI] & STATUSRSSI_ST) == 0)
tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
+ else
+ tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
/* mono/stereo selector */
- if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 1)
- tuner->audmode = V4L2_TUNER_MODE_MONO;
- else
+ if ((radio->registers[POWERCFG] & POWERCFG_MONO) == 0)
tuner->audmode = V4L2_TUNER_MODE_STEREO;
+ else
+ tuner->audmode = V4L2_TUNER_MODE_MONO;
/* min is worst, max is best; signal:0..0xffff; rssi: 0..0xff */
- tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI)
- * 0x0101;
+ /* measured in units of dbµV in 1 db increments (max at ~75 dbµV) */
+ tuner->signal = (radio->registers[STATUSRSSI] & STATUSRSSI_RSSI);
+ /* the ideal factor is 0xffff/75 = 873,8 */
+ tuner->signal = (tuner->signal * 873) + (8 * tuner->signal / 10);
/* automatic frequency control: -1: freq to low, 1 freq to high */
/* AFCRL does only indicate that freq. differs, not if too low/high */
@@ -1632,6 +1663,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
/* set initial frequency */
si470x_set_freq(radio, 87.5 * FREQ_MUL); /* available in all regions */
+ /* set led to connect state */
+ si470x_set_led_state(radio, BLINK_GREEN_LED);
+
/* rds buffer allocation */
radio->buf_size = rds_buf * 3;
radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
@@ -1715,6 +1749,9 @@ static void si470x_usb_driver_disconnect(struct usb_interface *intf)
cancel_delayed_work_sync(&radio->work);
usb_set_intfdata(intf, NULL);
if (radio->users == 0) {
+ /* set led to disconnect state */
+ si470x_set_led_state(radio, BLINK_ORANGE_LED);
+
video_unregister_device(radio->videodev);
kfree(radio->buffer);
kfree(radio);
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 2ed24527ecd6..65e4901f4db7 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -422,6 +422,7 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
if (urb == NULL)
break;
+ BUG_ON(!gspca_dev->dev);
gspca_dev->urb[i] = NULL;
if (!gspca_dev->present)
usb_kill_urb(urb);
@@ -1950,8 +1951,12 @@ void gspca_disconnect(struct usb_interface *intf)
{
struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+ mutex_lock(&gspca_dev->usb_lock);
gspca_dev->present = 0;
+ mutex_unlock(&gspca_dev->usb_lock);
+ destroy_urbs(gspca_dev);
+ gspca_dev->dev = NULL;
usb_set_intfdata(intf, NULL);
/* release the device */
diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c
index f6b3ef6e691b..c13bd2aa0bea 100644
--- a/drivers/media/video/ivtv/ivtv-ioctl.c
+++ b/drivers/media/video/ivtv/ivtv-ioctl.c
@@ -393,7 +393,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
return 0;
}
- v4l2_subdev_call(itv->sd_video, video, s_fmt, fmt);
+ v4l2_subdev_call(itv->sd_video, video, g_fmt, fmt);
vbifmt->service_set = ivtv_get_service_set(vbifmt);
return 0;
}
@@ -1748,6 +1748,18 @@ static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
break;
}
+ case IVTV_IOC_DMA_FRAME:
+ case VIDEO_GET_PTS:
+ case VIDEO_GET_FRAME_COUNT:
+ case VIDEO_GET_EVENT:
+ case VIDEO_PLAY:
+ case VIDEO_STOP:
+ case VIDEO_FREEZE:
+ case VIDEO_CONTINUE:
+ case VIDEO_COMMAND:
+ case VIDEO_TRY_COMMAND:
+ return ivtv_decoder_ioctls(file, cmd, (void *)arg);
+
default:
return -EINVAL;
}
@@ -1790,18 +1802,6 @@ static long ivtv_serialized_ioctl(struct ivtv *itv, struct file *filp,
ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode);
return 0;
- case IVTV_IOC_DMA_FRAME:
- case VIDEO_GET_PTS:
- case VIDEO_GET_FRAME_COUNT:
- case VIDEO_GET_EVENT:
- case VIDEO_PLAY:
- case VIDEO_STOP:
- case VIDEO_FREEZE:
- case VIDEO_CONTINUE:
- case VIDEO_COMMAND:
- case VIDEO_TRY_COMMAND:
- return ivtv_decoder_ioctls(filp, cmd, (void *)arg);
-
default:
break;
}
diff --git a/drivers/mfd/htc-egpio.c b/drivers/mfd/htc-egpio.c
index 1a4d04664d6d..aa266e1f69b2 100644
--- a/drivers/mfd/htc-egpio.c
+++ b/drivers/mfd/htc-egpio.c
@@ -286,7 +286,7 @@ static int __init egpio_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
goto fail;
- ei->base_addr = ioremap_nocache(res->start, res->end - res->start);
+ ei->base_addr = ioremap_nocache(res->start, resource_size(res));
if (!ei->base_addr)
goto fail;
pr_debug("EGPIO phys=%08x virt=%p\n", (u32)res->start, ei->base_addr);
@@ -307,7 +307,7 @@ static int __init egpio_probe(struct platform_device *pdev)
ei->nchips = pdata->num_chips;
ei->chip = kzalloc(sizeof(struct egpio_chip) * ei->nchips, GFP_KERNEL);
- if (!ei) {
+ if (!ei->chip) {
ret = -ENOMEM;
goto fail;
}
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index ea9488e7ad6d..2e36057659e1 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -678,6 +678,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
static struct i2c_device_id pcf50633_id_table[] = {
{"pcf50633", 0x73},
+ {/* end of list */}
};
static struct i2c_driver pcf50633_driver = {
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 0e5761f12634..4c7b7962f6b8 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1050,7 +1050,7 @@ static int __devinit sm501_gpio_register_chip(struct sm501_devdata *sm,
return gpiochip_add(gchip);
}
-static int sm501_register_gpio(struct sm501_devdata *sm)
+static int __devinit sm501_register_gpio(struct sm501_devdata *sm)
{
struct sm501_gpio *gpio = &sm->gpio;
resource_size_t iobase = sm->io_res->start + SM501_GPIO;
@@ -1321,7 +1321,7 @@ static unsigned int sm501_mem_local[] = {
* Common init code for an SM501
*/
-static int sm501_init_dev(struct sm501_devdata *sm)
+static int __devinit sm501_init_dev(struct sm501_devdata *sm)
{
struct sm501_initdata *idata;
struct sm501_platdata *pdata;
@@ -1397,7 +1397,7 @@ static int sm501_init_dev(struct sm501_devdata *sm)
return 0;
}
-static int sm501_plat_probe(struct platform_device *dev)
+static int __devinit sm501_plat_probe(struct platform_device *dev)
{
struct sm501_devdata *sm;
int ret;
@@ -1586,8 +1586,8 @@ static struct sm501_platdata sm501_pci_platdata = {
.gpio_base = -1,
};
-static int sm501_pci_probe(struct pci_dev *dev,
- const struct pci_device_id *id)
+static int __devinit sm501_pci_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
{
struct sm501_devdata *sm;
int err;
@@ -1693,7 +1693,7 @@ static void sm501_dev_remove(struct sm501_devdata *sm)
sm501_gpio_remove(sm);
}
-static void sm501_pci_remove(struct pci_dev *dev)
+static void __devexit sm501_pci_remove(struct pci_dev *dev)
{
struct sm501_devdata *sm = pci_get_drvdata(dev);
@@ -1727,16 +1727,16 @@ static struct pci_device_id sm501_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, sm501_pci_tbl);
-static struct pci_driver sm501_pci_drv = {
+static struct pci_driver sm501_pci_driver = {
.name = "sm501",
.id_table = sm501_pci_tbl,
.probe = sm501_pci_probe,
- .remove = sm501_pci_remove,
+ .remove = __devexit_p(sm501_pci_remove),
};
MODULE_ALIAS("platform:sm501");
-static struct platform_driver sm501_plat_drv = {
+static struct platform_driver sm501_plat_driver = {
.driver = {
.name = "sm501",
.owner = THIS_MODULE,
@@ -1749,14 +1749,14 @@ static struct platform_driver sm501_plat_drv = {
static int __init sm501_base_init(void)
{
- platform_driver_register(&sm501_plat_drv);
- return pci_register_driver(&sm501_pci_drv);
+ platform_driver_register(&sm501_plat_driver);
+ return pci_register_driver(&sm501_pci_driver);
}
static void __exit sm501_base_exit(void)
{
- platform_driver_unregister(&sm501_plat_drv);
- pci_unregister_driver(&sm501_pci_drv);
+ platform_driver_unregister(&sm501_plat_driver);
+ pci_unregister_driver(&sm501_pci_driver);
}
module_init(sm501_base_init);
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
index e7ab0035d305..68826f1e36bc 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl4030-core.c
@@ -38,7 +38,7 @@
#include <linux/i2c.h>
#include <linux/i2c/twl4030.h>
-#ifdef CONFIG_ARM
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
#include <mach/cpu.h>
#endif
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c
index f92595c8f165..84d5ea1ec171 100644
--- a/drivers/mfd/wm8350-core.c
+++ b/drivers/mfd/wm8350-core.c
@@ -1111,7 +1111,7 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref)
do {
schedule_timeout_interruptible(1);
reg = wm8350_reg_read(wm8350, WM8350_DIGITISER_CONTROL_1);
- } while (tries-- && (reg & WM8350_AUXADC_POLL));
+ } while (--tries && (reg & WM8350_AUXADC_POLL));
if (!tries)
dev_err(wm8350->dev, "adc chn %d read timeout\n", channel);
@@ -1297,14 +1297,29 @@ static void wm8350_client_dev_register(struct wm8350 *wm8350,
int wm8350_device_init(struct wm8350 *wm8350, int irq,
struct wm8350_platform_data *pdata)
{
- int ret = -EINVAL;
+ int ret;
u16 id1, id2, mask_rev;
u16 cust_id, mode, chip_rev;
/* get WM8350 revision and config mode */
- wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
- wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
- wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev), &mask_rev);
+ ret = wm8350->read_dev(wm8350, WM8350_RESET_ID, sizeof(id1), &id1);
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Failed to read ID: %d\n", ret);
+ goto err;
+ }
+
+ ret = wm8350->read_dev(wm8350, WM8350_ID, sizeof(id2), &id2);
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Failed to read ID: %d\n", ret);
+ goto err;
+ }
+
+ ret = wm8350->read_dev(wm8350, WM8350_REVISION, sizeof(mask_rev),
+ &mask_rev);
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Failed to read revision: %d\n", ret);
+ goto err;
+ }
id1 = be16_to_cpu(id1);
id2 = be16_to_cpu(id2);
@@ -1404,14 +1419,12 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
return ret;
}
- if (pdata && pdata->init) {
- ret = pdata->init(wm8350);
- if (ret != 0) {
- dev_err(wm8350->dev, "Platform init() failed: %d\n",
- ret);
- goto err;
- }
- }
+ wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0xFFFF);
+ wm8350_reg_write(wm8350, WM8350_INT_STATUS_1_MASK, 0xFFFF);
+ wm8350_reg_write(wm8350, WM8350_INT_STATUS_2_MASK, 0xFFFF);
+ wm8350_reg_write(wm8350, WM8350_UNDER_VOLTAGE_INT_STATUS_MASK, 0xFFFF);
+ wm8350_reg_write(wm8350, WM8350_GPIO_INT_STATUS_MASK, 0xFFFF);
+ wm8350_reg_write(wm8350, WM8350_COMPARATOR_INT_STATUS_MASK, 0xFFFF);
mutex_init(&wm8350->auxadc_mutex);
mutex_init(&wm8350->irq_mutex);
@@ -1430,6 +1443,15 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq,
}
wm8350->chip_irq = irq;
+ if (pdata && pdata->init) {
+ ret = pdata->init(wm8350);
+ if (ret != 0) {
+ dev_err(wm8350->dev, "Platform init() failed: %d\n",
+ ret);
+ goto err;
+ }
+ }
+
wm8350_reg_write(wm8350, WM8350_SYSTEM_INTERRUPTS_MASK, 0x0);
wm8350_client_dev_register(wm8350, "wm8350-codec",
diff --git a/drivers/mfd/wm8350-regmap.c b/drivers/mfd/wm8350-regmap.c
index 68887b817d17..9a4cc954cb7c 100644
--- a/drivers/mfd/wm8350-regmap.c
+++ b/drivers/mfd/wm8350-regmap.c
@@ -3188,7 +3188,7 @@ const struct wm8350_reg_access wm8350_reg_io_map[] = {
{ 0x7CFF, 0x0C00, 0x7FFF }, /* R1 - ID */
{ 0x0000, 0x0000, 0x0000 }, /* R2 */
{ 0xBE3B, 0xBE3B, 0x8000 }, /* R3 - System Control 1 */
- { 0xFCF7, 0xFCF7, 0xF800 }, /* R4 - System Control 2 */
+ { 0xFEF7, 0xFEF7, 0xF800 }, /* R4 - System Control 2 */
{ 0x80FF, 0x80FF, 0x8000 }, /* R5 - System Hibernate */
{ 0xFB0E, 0xFB0E, 0x0000 }, /* R6 - Interface Control */
{ 0x0000, 0x0000, 0x0000 }, /* R7 */
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 45b1f430685f..513eb09a638f 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -584,7 +584,7 @@ static int mmc_blk_probe(struct mmc_card *card)
if (err)
goto out;
- string_get_size(get_capacity(md->disk) << 9, STRING_UNITS_2,
+ string_get_size((u64)get_capacity(md->disk) << 9, STRING_UNITS_2,
cap_str, sizeof(cap_str));
printk(KERN_INFO "%s: %s %s %s %s\n",
md->disk->disk_name, mmc_card_id(card), mmc_card_name(card),
diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c
index b92b172074ee..b9f1e84897cc 100644
--- a/drivers/mmc/card/mmc_test.c
+++ b/drivers/mmc/card/mmc_test.c
@@ -494,7 +494,7 @@ static int mmc_test_basic_read(struct mmc_test_card *test)
sg_init_one(&sg, test->buffer, 512);
- ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 1);
+ ret = mmc_test_simple_transfer(test, &sg, 1, 0, 1, 512, 0);
if (ret)
return ret;
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c
index 76bfe16c09b1..2b1196e6142c 100644
--- a/drivers/mmc/host/atmel-mci.c
+++ b/drivers/mmc/host/atmel-mci.c
@@ -1548,9 +1548,10 @@ static bool filter(struct dma_chan *chan, void *slave)
{
struct dw_dma_slave *dws = slave;
- if (dws->dma_dev == chan->device->dev)
+ if (dws->dma_dev == chan->device->dev) {
+ chan->private = dws;
return true;
- else
+ } else
return false;
}
#endif
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index db37490f67ec..a631c81dce12 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -55,6 +55,7 @@
#define VS30 (1 << 25)
#define SDVS18 (0x5 << 9)
#define SDVS30 (0x6 << 9)
+#define SDVS33 (0x7 << 9)
#define SDVSCLR 0xFFFFF1FF
#define SDVSDET 0x00000400
#define AUTOIDLE 0x1
@@ -375,6 +376,32 @@ static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status)
}
#endif /* CONFIG_MMC_DEBUG */
+/*
+ * MMC controller internal state machines reset
+ *
+ * Used to reset command or data internal state machines, using respectively
+ * SRC or SRD bit of SYSCTL register
+ * Can be called from interrupt context
+ */
+static inline void mmc_omap_reset_controller_fsm(struct mmc_omap_host *host,
+ unsigned long bit)
+{
+ unsigned long i = 0;
+ unsigned long limit = (loops_per_jiffy *
+ msecs_to_jiffies(MMC_TIMEOUT_MS));
+
+ OMAP_HSMMC_WRITE(host->base, SYSCTL,
+ OMAP_HSMMC_READ(host->base, SYSCTL) | bit);
+
+ while ((OMAP_HSMMC_READ(host->base, SYSCTL) & bit) &&
+ (i++ < limit))
+ cpu_relax();
+
+ if (OMAP_HSMMC_READ(host->base, SYSCTL) & bit)
+ dev_err(mmc_dev(host->mmc),
+ "Timeout waiting on controller reset in %s\n",
+ __func__);
+}
/*
* MMC controller IRQ handler
@@ -403,21 +430,17 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
(status & CMD_CRC)) {
if (host->cmd) {
if (status & CMD_TIMEOUT) {
- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base,
- SYSCTL) | SRC);
- while (OMAP_HSMMC_READ(host->base,
- SYSCTL) & SRC)
- ;
-
+ mmc_omap_reset_controller_fsm(host, SRC);
host->cmd->error = -ETIMEDOUT;
} else {
host->cmd->error = -EILSEQ;
}
end_cmd = 1;
}
- if (host->data)
+ if (host->data) {
mmc_dma_cleanup(host);
+ mmc_omap_reset_controller_fsm(host, SRD);
+ }
}
if ((status & DATA_TIMEOUT) ||
(status & DATA_CRC)) {
@@ -426,12 +449,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
mmc_dma_cleanup(host);
else
host->data->error = -EILSEQ;
- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base,
- SYSCTL) | SRD);
- while (OMAP_HSMMC_READ(host->base,
- SYSCTL) & SRD)
- ;
+ mmc_omap_reset_controller_fsm(host, SRD);
end_trans = 1;
}
}
@@ -456,13 +474,20 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
}
/*
- * Switch MMC operating voltage
+ * Switch MMC interface voltage ... only relevant for MMC1.
+ *
+ * MMC2 and MMC3 use fixed 1.8V levels, and maybe a transceiver.
+ * The MMC2 transceiver controls are used instead of DAT4..DAT7.
+ * Some chips, like eMMC ones, use internal transceivers.
*/
static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
{
u32 reg_val = 0;
int ret;
+ if (host->id != OMAP_MMC1_DEVID)
+ return 0;
+
/* Disable the clocks */
clk_disable(host->fclk);
clk_disable(host->iclk);
@@ -485,19 +510,26 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd)
OMAP_HSMMC_WRITE(host->base, HCTL,
OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR);
reg_val = OMAP_HSMMC_READ(host->base, HCTL);
+
/*
* If a MMC dual voltage card is detected, the set_ios fn calls
* this fn with VDD bit set for 1.8V. Upon card removal from the
* slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF.
*
- * Only MMC1 supports 3.0V. MMC2 will not function if SDVS30 is
- * set in HCTL.
+ * Cope with a bit of slop in the range ... per data sheets:
+ * - "1.8V" for vdds_mmc1/vdds_mmc1a can be up to 2.45V max,
+ * but recommended values are 1.71V to 1.89V
+ * - "3.0V" for vdds_mmc1/vdds_mmc1a can be up to 3.5V max,
+ * but recommended values are 2.7V to 3.3V
+ *
+ * Board setup code shouldn't permit anything very out-of-range.
+ * TWL4030-family VMMC1 and VSIM regulators are fine (avoiding the
+ * middle range) but VSIM can't power DAT4..DAT7 at more than 3V.
*/
- if (host->id == OMAP_MMC1_DEVID && (((1 << vdd) == MMC_VDD_32_33) ||
- ((1 << vdd) == MMC_VDD_33_34)))
- reg_val |= SDVS30;
- if ((1 << vdd) == MMC_VDD_165_195)
+ if ((1 << vdd) <= MMC_VDD_23_24)
reg_val |= SDVS18;
+ else
+ reg_val |= SDVS30;
OMAP_HSMMC_WRITE(host->base, HCTL, reg_val);
@@ -517,16 +549,15 @@ static void mmc_omap_detect(struct work_struct *work)
{
struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
mmc_carddetect_work);
+ struct omap_mmc_slot_data *slot = &mmc_slot(host);
+
+ host->carddetect = slot->card_detect(slot->card_detect_irq);
sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
if (host->carddetect) {
mmc_detect_change(host->mmc, (HZ * 200) / 1000);
} else {
- OMAP_HSMMC_WRITE(host->base, SYSCTL,
- OMAP_HSMMC_READ(host->base, SYSCTL) | SRD);
- while (OMAP_HSMMC_READ(host->base, SYSCTL) & SRD)
- ;
-
+ mmc_omap_reset_controller_fsm(host, SRD);
mmc_detect_change(host->mmc, (HZ * 50) / 1000);
}
}
@@ -538,7 +569,6 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
{
struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
- host->carddetect = mmc_slot(host).card_detect(irq);
schedule_work(&host->mmc_carddetect_work);
return IRQ_HANDLED;
@@ -757,10 +787,14 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
case MMC_POWER_OFF:
mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
/*
- * Reset bus voltage to 3V if it got set to 1.8V earlier.
+ * Reset interface voltage to 3V if it's 1.8V now;
+ * only relevant on MMC-1, the others always use 1.8V.
+ *
* REVISIT: If we are able to detect cards after unplugging
* a 1.8V card, this code should not be needed.
*/
+ if (host->id != OMAP_MMC1_DEVID)
+ break;
if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
int vdd = fls(host->mmc->ocr_avail) - 1;
if (omap_mmc_switch_opcond(host, vdd) != 0)
@@ -784,7 +818,9 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
}
if (host->id == OMAP_MMC1_DEVID) {
- /* Only MMC1 can operate at 3V/1.8V */
+ /* Only MMC1 can interface at 3V without some flavor
+ * of external transceiver; but they all handle 1.8V.
+ */
if ((OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET) &&
(ios->vdd == DUAL_VOLT_OCR_BIT)) {
/*
@@ -1137,7 +1173,9 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
" level suspend\n");
}
- if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) {
+ if (host->id == OMAP_MMC1_DEVID
+ && !(OMAP_HSMMC_READ(host->base, HCTL)
+ & SDVSDET)) {
OMAP_HSMMC_WRITE(host->base, HCTL,
OMAP_HSMMC_READ(host->base, HCTL)
& SDVSCLR);
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c
index 35a98eec7414..f4a67c65d301 100644
--- a/drivers/mmc/host/s3cmci.c
+++ b/drivers/mmc/host/s3cmci.c
@@ -329,7 +329,7 @@ static void do_pio_write(struct s3cmci_host *host)
to_ptr = host->base + host->sdidata;
- while ((fifo = fifo_free(host))) {
+ while ((fifo = fifo_free(host)) > 3) {
if (!host->pio_bytes) {
res = get_data_buffer(host, &host->pio_bytes,
&host->pio_ptr);
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index f07255cb17ee..8cff5f5e7f86 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -144,8 +144,7 @@ static int jmicron_probe(struct sdhci_pci_chip *chip)
SDHCI_QUIRK_32BIT_DMA_SIZE |
SDHCI_QUIRK_32BIT_ADMA_SIZE |
SDHCI_QUIRK_RESET_AFTER_REQUEST |
- SDHCI_QUIRK_BROKEN_SMALL_PIO |
- SDHCI_QUIRK_FORCE_HIGHSPEED;
+ SDHCI_QUIRK_BROKEN_SMALL_PIO;
}
/*
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 6b2d1f99af67..f52f3053ed92 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1636,8 +1636,7 @@ int sdhci_add_host(struct sdhci_host *host)
mmc->f_max = host->max_clk;
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
- if ((caps & SDHCI_CAN_DO_HISPD) ||
- (host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED))
+ if (caps & SDHCI_CAN_DO_HISPD)
mmc->caps |= MMC_CAP_SD_HIGHSPEED;
mmc->ocr_avail = 0;
@@ -1723,7 +1722,9 @@ int sdhci_add_host(struct sdhci_host *host)
#endif
#ifdef SDHCI_USE_LEDS_CLASS
- host->led.name = mmc_hostname(mmc);
+ snprintf(host->led_name, sizeof(host->led_name),
+ "%s::", mmc_hostname(mmc));
+ host->led.name = host->led_name;
host->led.brightness = LED_OFF;
host->led.default_trigger = mmc_hostname(mmc);
host->led.brightness_set = sdhci_led_control;
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 3efba2363941..ebb83657e27a 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -208,8 +208,6 @@ struct sdhci_host {
#define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12)
/* Controller has an issue with buffer bits for small transfers */
#define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13)
-/* Controller supports high speed but doesn't have the caps bit set */
-#define SDHCI_QUIRK_FORCE_HIGHSPEED (1<<14)
int irq; /* Device IRQ */
void __iomem * ioaddr; /* Mapped address */
@@ -222,6 +220,7 @@ struct sdhci_host {
#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE)
struct led_classdev led; /* LED control */
+ char led_name[32];
#endif
spinlock_t lock; /* Mutex */
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index c98c1570a40b..47a33cec3793 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -139,7 +139,8 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
struct nand_chip *nand_chip = mtd->priv;
struct atmel_nand_host *host = nand_chip->priv;
- return gpio_get_value(host->board->rdy_pin);
+ return gpio_get_value(host->board->rdy_pin) ^
+ !!host->board->rdy_pin_active_low;
}
/*
diff --git a/drivers/parport/parport_atari.c b/drivers/parport/parport_atari.c
index ad4cdd256137..0b28fccec03f 100644
--- a/drivers/parport/parport_atari.c
+++ b/drivers/parport/parport_atari.c
@@ -84,7 +84,7 @@ parport_atari_frob_control(struct parport *p, unsigned char mask,
static unsigned char
parport_atari_read_status(struct parport *p)
{
- return ((mfp.par_dt_reg & 1 ? 0 : PARPORT_STATUS_BUSY) |
+ return ((st_mfp.par_dt_reg & 1 ? 0 : PARPORT_STATUS_BUSY) |
PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR);
}
@@ -193,9 +193,9 @@ static int __init parport_atari_init(void)
sound_ym.wd_data = sound_ym.rd_data_reg_sel | (1 << 5);
local_irq_restore(flags);
/* MFP port I0 as input. */
- mfp.data_dir &= ~1;
+ st_mfp.data_dir &= ~1;
/* MFP port I0 interrupt on high->low edge. */
- mfp.active_edge &= ~1;
+ st_mfp.active_edge &= ~1;
p = parport_register_port((unsigned long)&sound_ym.wd_data,
IRQ_MFP_BUSY, PARPORT_DMA_NONE,
&parport_atari_ops);
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
index f4b7c79023ff..f3f686581a90 100644
--- a/drivers/pci/intel-iommu.c
+++ b/drivers/pci/intel-iommu.c
@@ -61,6 +61,8 @@
/* global iommu list, set NULL for ignored DMAR units */
static struct intel_iommu **g_iommus;
+static int rwbf_quirk;
+
/*
* 0: Present
* 1-11: Reserved
@@ -785,7 +787,7 @@ static void iommu_flush_write_buffer(struct intel_iommu *iommu)
u32 val;
unsigned long flag;
- if (!cap_rwbf(iommu->cap))
+ if (!rwbf_quirk && !cap_rwbf(iommu->cap))
return;
val = iommu->gcmd | DMA_GCMD_WBF;
@@ -3137,3 +3139,15 @@ static struct iommu_ops intel_iommu_ops = {
.unmap = intel_iommu_unmap_range,
.iova_to_phys = intel_iommu_iova_to_phys,
};
+
+static void __devinit quirk_iommu_rwbf(struct pci_dev *dev)
+{
+ /*
+ * Mobile 4 Series Chipset neglects to set RWBF capability,
+ * but needs it:
+ */
+ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
+ rwbf_quirk = 1;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 44f15ff70c1d..baba2eb5367d 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -103,14 +103,12 @@ static void msix_set_enable(struct pci_dev *dev, int enable)
}
}
-/*
- * Essentially, this is ((1 << (1 << x)) - 1), but without the
- * undefinedness of a << 32.
- */
static inline __attribute_const__ u32 msi_mask(unsigned x)
{
- static const u32 mask[] = { 1, 2, 4, 0xf, 0xff, 0xffff, 0xffffffff };
- return mask[x];
+ /* Don't shift by >= width of type */
+ if (x >= 5)
+ return 0xffffffff;
+ return (1 << (1 << x)) - 1;
}
static void msix_flush_writes(struct irq_desc *desc)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e3efe6b19ee7..6d6120007af4 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1540,16 +1540,21 @@ void pci_release_region(struct pci_dev *pdev, int bar)
}
/**
- * pci_request_region - Reserved PCI I/O and memory resource
+ * __pci_request_region - Reserved PCI I/O and memory resource
* @pdev: PCI device whose resources are to be reserved
* @bar: BAR to be reserved
* @res_name: Name to be associated with resource.
+ * @exclusive: whether the region access is exclusive or not
*
* Mark the PCI region associated with PCI device @pdev BR @bar as
* being reserved by owner @res_name. Do not access any
* address inside the PCI regions unless this call returns
* successfully.
*
+ * If @exclusive is set, then the region is marked so that userspace
+ * is explicitly not allowed to map the resource via /dev/mem or
+ * sysfs MMIO access.
+ *
* Returns 0 on success, or %EBUSY on error. A warning
* message is also printed on failure.
*/
@@ -1588,12 +1593,12 @@ err_out:
}
/**
- * pci_request_region - Reserved PCI I/O and memory resource
+ * pci_request_region - Reserve PCI I/O and memory resource
* @pdev: PCI device whose resources are to be reserved
* @bar: BAR to be reserved
- * @res_name: Name to be associated with resource.
+ * @res_name: Name to be associated with resource
*
- * Mark the PCI region associated with PCI device @pdev BR @bar as
+ * Mark the PCI region associated with PCI device @pdev BAR @bar as
* being reserved by owner @res_name. Do not access any
* address inside the PCI regions unless this call returns
* successfully.
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 26ddf78ac300..07c0aa5275e6 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -16,21 +16,21 @@ extern int pci_mmap_fits(struct pci_dev *pdev, int resno,
#endif
/**
- * Firmware PM callbacks
+ * struct pci_platform_pm_ops - Firmware PM callbacks
*
- * @is_manageable - returns 'true' if given device is power manageable by the
- * platform firmware
+ * @is_manageable: returns 'true' if given device is power manageable by the
+ * platform firmware
*
- * @set_state - invokes the platform firmware to set the device's power state
+ * @set_state: invokes the platform firmware to set the device's power state
*
- * @choose_state - returns PCI power state of given device preferred by the
- * platform; to be used during system-wide transitions from a
- * sleeping state to the working state and vice versa
+ * @choose_state: returns PCI power state of given device preferred by the
+ * platform; to be used during system-wide transitions from a
+ * sleeping state to the working state and vice versa
*
- * @can_wakeup - returns 'true' if given device is capable of waking up the
- * system from a sleeping state
+ * @can_wakeup: returns 'true' if given device is capable of waking up the
+ * system from a sleeping state
*
- * @sleep_wake - enables/disables the system wake up capability of given device
+ * @sleep_wake: enables/disables the system wake up capability of given device
*
* If given platform is generally capable of power managing PCI devices, all of
* these callbacks are mandatory.
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c
index 29cbe47f219f..36864a935d68 100644
--- a/drivers/pci/rom.c
+++ b/drivers/pci/rom.c
@@ -55,6 +55,7 @@ void pci_disable_rom(struct pci_dev *pdev)
/**
* pci_get_rom_size - obtain the actual size of the ROM image
+ * @pdev: target PCI device
* @rom: kernel virtual pointer to image of ROM
* @size: size of PCI window
* return: size of actual ROM image
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 94363115a42a..b3866ad50227 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -62,6 +62,7 @@ config DELL_LAPTOP
depends on EXPERIMENTAL
depends on BACKLIGHT_CLASS_DEVICE
depends on RFKILL
+ depends on POWER_SUPPLY
default n
---help---
This driver adds support for rfkill and backlight control to Dell
@@ -301,6 +302,7 @@ config INTEL_MENLOW
config EEEPC_LAPTOP
tristate "Eee PC Hotkey Driver (EXPERIMENTAL)"
depends on ACPI
+ depends on INPUT
depends on EXPERIMENTAL
select BACKLIGHT_CLASS_DEVICE
select HWMON
diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c
index 65dc41540c62..45940f31fe9e 100644
--- a/drivers/platform/x86/fujitsu-laptop.c
+++ b/drivers/platform/x86/fujitsu-laptop.c
@@ -166,6 +166,7 @@ struct fujitsu_hotkey_t {
struct platform_device *pf_device;
struct kfifo *fifo;
spinlock_t fifo_lock;
+ int rfkill_supported;
int rfkill_state;
int logolamp_registered;
int kblamps_registered;
@@ -526,7 +527,7 @@ static ssize_t
show_lid_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+ if (!(fujitsu_hotkey->rfkill_supported & 0x100))
return sprintf(buf, "unknown\n");
if (fujitsu_hotkey->rfkill_state & 0x100)
return sprintf(buf, "open\n");
@@ -538,7 +539,7 @@ static ssize_t
show_dock_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+ if (!(fujitsu_hotkey->rfkill_supported & 0x200))
return sprintf(buf, "unknown\n");
if (fujitsu_hotkey->rfkill_state & 0x200)
return sprintf(buf, "docked\n");
@@ -550,7 +551,7 @@ static ssize_t
show_radios_state(struct device *dev,
struct device_attribute *attr, char *buf)
{
- if (fujitsu_hotkey->rfkill_state == UNSUPPORTED_CMD)
+ if (!(fujitsu_hotkey->rfkill_supported & 0x20))
return sprintf(buf, "unknown\n");
if (fujitsu_hotkey->rfkill_state & 0x20)
return sprintf(buf, "on\n");
@@ -928,8 +929,17 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device)
; /* No action, result is discarded */
vdbg_printk(FUJLAPTOP_DBG_INFO, "Discarded %i ringbuffer entries\n", i);
- fujitsu_hotkey->rfkill_state =
- call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
+ fujitsu_hotkey->rfkill_supported =
+ call_fext_func(FUNC_RFKILL, 0x0, 0x0, 0x0);
+
+ /* Make sure our bitmask of supported functions is cleared if the
+ RFKILL function block is not implemented, like on the S7020. */
+ if (fujitsu_hotkey->rfkill_supported == UNSUPPORTED_CMD)
+ fujitsu_hotkey->rfkill_supported = 0;
+
+ if (fujitsu_hotkey->rfkill_supported)
+ fujitsu_hotkey->rfkill_state =
+ call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
/* Suspect this is a keymap of the application panel, print it */
printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n",
@@ -1005,8 +1015,9 @@ static void acpi_fujitsu_hotkey_notify(acpi_handle handle, u32 event,
input = fujitsu_hotkey->input;
- fujitsu_hotkey->rfkill_state =
- call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
+ if (fujitsu_hotkey->rfkill_supported)
+ fujitsu_hotkey->rfkill_state =
+ call_fext_func(FUNC_RFKILL, 0x4, 0x0, 0x0);
switch (event) {
case ACPI_FUJITSU_NOTIFY_CODE1:
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 1fd8f2193ed8..4377e93a43d7 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -280,8 +280,11 @@ sclp_dispatch_evbufs(struct sccb_header *sccb)
rc = 0;
for (offset = sizeof(struct sccb_header); offset < sccb->length;
offset += evbuf->length) {
- /* Search for event handler */
evbuf = (struct evbuf_header *) ((addr_t) sccb + offset);
+ /* Check for malformed hardware response */
+ if (evbuf->length == 0)
+ break;
+ /* Search for event handler */
reg = NULL;
list_for_each(l, &sclp_reg_list) {
reg = list_entry(l, struct sclp_register, list);
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c
index 506390496416..77ab6e34a100 100644
--- a/drivers/s390/char/sclp_cmd.c
+++ b/drivers/s390/char/sclp_cmd.c
@@ -19,6 +19,7 @@
#include <linux/memory.h>
#include <asm/chpid.h>
#include <asm/sclp.h>
+#include <asm/setup.h>
#include "sclp.h"
@@ -474,6 +475,10 @@ static void __init add_memory_merged(u16 rn)
goto skip_add;
if (start + size > VMEM_MAX_PHYS)
size = VMEM_MAX_PHYS - start;
+ if (memory_end_set && (start >= memory_end))
+ goto skip_add;
+ if (memory_end_set && (start + size > memory_end))
+ size = memory_end - start;
add_memory(0, start, size);
skip_add:
first_rn = rn;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index a1a511bdec8c..ed1e728763a2 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1573,9 +1573,6 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
vfc_cmd->resp_len = sizeof(vfc_cmd->rsp);
vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata;
vfc_cmd->tgt_scsi_id = rport->port_id;
- if ((rport->supported_classes & FC_COS_CLASS3) &&
- (fc_host_supported_classes(vhost->host) & FC_COS_CLASS3))
- vfc_cmd->flags = IBMVFC_CLASS_3_ERR;
vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd);
int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun);
memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len);
@@ -3266,6 +3263,7 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id)
return -ENOMEM;
}
+ memset(tgt, 0, sizeof(*tgt));
tgt->scsi_id = scsi_id;
tgt->new_scsi_id = scsi_id;
tgt->vhost = vhost;
@@ -3576,9 +3574,18 @@ static void ibmvfc_log_ae(struct ibmvfc_host *vhost, int events)
static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
{
struct ibmvfc_host *vhost = tgt->vhost;
- struct fc_rport *rport;
+ struct fc_rport *rport = tgt->rport;
unsigned long flags;
+ if (rport) {
+ tgt_dbg(tgt, "Setting rport roles\n");
+ fc_remote_port_rolechg(rport, tgt->ids.roles);
+ spin_lock_irqsave(vhost->host->host_lock, flags);
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ return;
+ }
+
tgt_dbg(tgt, "Adding rport\n");
rport = fc_remote_port_add(vhost->host, 0, &tgt->ids);
spin_lock_irqsave(vhost->host->host_lock, flags);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 87dafd0f8d44..b21e071b9862 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -32,7 +32,7 @@
#define IBMVFC_DRIVER_VERSION "1.0.4"
#define IBMVFC_DRIVER_DATE "(November 14, 2008)"
-#define IBMVFC_DEFAULT_TIMEOUT 15
+#define IBMVFC_DEFAULT_TIMEOUT 60
#define IBMVFC_INIT_TIMEOUT 120
#define IBMVFC_MAX_REQUESTS_DEFAULT 100
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 74d07d137dae..c9aa7611e408 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -432,6 +432,7 @@ static int map_sg_data(struct scsi_cmnd *cmd,
sdev_printk(KERN_ERR, cmd->device,
"Can't allocate memory "
"for indirect table\n");
+ scsi_dma_unmap(cmd);
return 0;
}
}
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 257c24115de9..809d32d95c76 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -1998,6 +1998,8 @@ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
if (!shost->can_queue)
shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX;
+ if (!shost->transportt->eh_timed_out)
+ shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
return scsi_add_host(shost, pdev);
}
EXPORT_SYMBOL_GPL(iscsi_host_add);
@@ -2020,7 +2022,6 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
if (!shost)
return NULL;
- shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
if (qdepth != 0)
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index a8f30bdaff69..a7302480bc4a 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -5258,6 +5258,7 @@ lpfc_send_els_event(struct lpfc_vport *vport,
sizeof(struct lpfc_name));
break;
default:
+ kfree(els_data);
return;
}
memcpy(els_data->wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 33a3c13fd893..f4c57227ec18 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -1265,13 +1265,6 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags))
msleep(1000);
- if (ha->mqenable) {
- if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
- qla_printk(KERN_WARNING, ha,
- "Queue delete failed.\n");
- vha->req_ques[0] = ha->req_q_map[0]->id;
- }
-
qla24xx_disable_vp(vha);
fc_remove_host(vha->host);
@@ -1293,6 +1286,12 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
vha->host_no, vha->vp_idx, vha));
}
+ if (ha->mqenable) {
+ if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
+ qla_printk(KERN_WARNING, ha,
+ "Queue delete failed.\n");
+ }
+
scsi_host_put(vha->host);
qla_printk(KERN_INFO, ha, "vport %d deleted\n", id);
return 0;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 023ee77fb027..e0c5bb54b258 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -2135,6 +2135,7 @@ struct qla_msix_entry {
/* Work events. */
enum qla_work_type {
QLA_EVT_AEN,
+ QLA_EVT_IDC_ACK,
};
@@ -2149,6 +2150,10 @@ struct qla_work_evt {
enum fc_host_event_code code;
u32 data;
} aen;
+ struct {
+#define QLA_IDC_ACK_REGS 7
+ uint16_t mb[QLA_IDC_ACK_REGS];
+ } idc_ack;
} u;
};
diff --git a/drivers/scsi/qla2xxx/qla_devtbl.h b/drivers/scsi/qla2xxx/qla_devtbl.h
index d78d35e681ab..d6ea69df7c5c 100644
--- a/drivers/scsi/qla2xxx/qla_devtbl.h
+++ b/drivers/scsi/qla2xxx/qla_devtbl.h
@@ -72,7 +72,7 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = {
"QLA2462", "Sun PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x141 */
"QLE2460", "Sun PCI-Express to 2Gb FC, Single Channel", /* 0x142 */
"QLE2462", "Sun PCI-Express to 4Gb FC, Single Channel", /* 0x143 */
- "QEM2462" "Server I/O Module 4Gb FC, Dual Channel", /* 0x144 */
+ "QEM2462", "Server I/O Module 4Gb FC, Dual Channel", /* 0x144 */
"QLE2440", "PCI-Express to 4Gb FC, Single Channel", /* 0x145 */
"QLE2464", "PCI-Express to 4Gb FC, Quad Channel", /* 0x146 */
"QLA2440", "PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x147 */
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 7abb045a0410..ffff42554087 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1402,6 +1402,8 @@ struct access_chip_rsp_84xx {
#define MBA_IDC_NOTIFY 0x8101
#define MBA_IDC_TIME_EXT 0x8102
+#define MBC_IDC_ACK 0x101
+
struct nvram_81xx {
/* NVRAM header. */
uint8_t id[4];
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index a336b4bc81a7..6de283f8f111 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -72,6 +72,7 @@ extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
fc_host_event_code, u32);
+extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
extern void qla2x00_abort_fcport_cmds(fc_port_t *);
extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
@@ -266,6 +267,8 @@ qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
+extern int qla81xx_idc_ack(scsi_qla_host_t *, uint16_t *);
+
/*
* Global Function Prototypes in qla_isr.c source file.
*/
@@ -376,10 +379,8 @@ extern int qla2x00_dfs_remove(scsi_qla_host_t *);
/* Globa function prototypes for multi-q */
extern int qla25xx_request_irq(struct rsp_que *);
-extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *,
- uint8_t);
-extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *,
- uint8_t);
+extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
+extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
uint16_t, uint8_t, uint8_t);
extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f6368a1d3021..986501759ad4 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1226,9 +1226,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
icb->firmware_options_2 |=
__constant_cpu_to_le32(BIT_18);
- icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_22);
+ icb->firmware_options_2 &= __constant_cpu_to_le32(~BIT_22);
icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23);
- ha->rsp_q_map[0]->options = icb->firmware_options_2;
WRT_REG_DWORD(&reg->isp25mq.req_q_in, 0);
WRT_REG_DWORD(&reg->isp25mq.req_q_out, 0);
@@ -3493,7 +3492,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
rsp = ha->rsp_q_map[i];
if (rsp) {
rsp->options &= ~BIT_0;
- ret = qla25xx_init_rsp_que(base_vha, rsp, rsp->options);
+ ret = qla25xx_init_rsp_que(base_vha, rsp);
if (ret != QLA_SUCCESS)
DEBUG2_17(printk(KERN_WARNING
"%s Rsp que:%d init failed\n", __func__,
@@ -3507,7 +3506,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
if (req) {
/* Clear outstanding commands array. */
req->options &= ~BIT_0;
- ret = qla25xx_init_req_que(base_vha, req, req->options);
+ ret = qla25xx_init_req_que(base_vha, req);
if (ret != QLA_SUCCESS)
DEBUG2_17(printk(KERN_WARNING
"%s Req que:%d init failed\n", __func__,
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index e28ad81baf1e..f250e5b7897c 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -266,6 +266,40 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
}
}
+static void
+qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
+{
+ static char *event[] =
+ { "Complete", "Request Notification", "Time Extension" };
+ int rval;
+ struct device_reg_24xx __iomem *reg24 = &vha->hw->iobase->isp24;
+ uint16_t __iomem *wptr;
+ uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];
+
+ /* Seed data -- mailbox1 -> mailbox7. */
+ wptr = (uint16_t __iomem *)&reg24->mailbox1;
+ for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
+ mb[cnt] = RD_REG_WORD(wptr);
+
+ DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
+ "%04x %04x %04x %04x %04x %04x %04x.\n", vha->host_no,
+ event[aen & 0xff],
+ mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]));
+
+ /* Acknowledgement needed? [Notify && non-zero timeout]. */
+ timeout = (descr >> 8) & 0xf;
+ if (aen != MBA_IDC_NOTIFY || !timeout)
+ return;
+
+ DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
+ "ACK timeout=%d.\n", vha->host_no, event[aen & 0xff], timeout));
+
+ rval = qla2x00_post_idc_ack_work(vha, mb);
+ if (rval != QLA_SUCCESS)
+ qla_printk(KERN_WARNING, vha->hw,
+ "IDC failed to post ACK.\n");
+}
+
/**
* qla2x00_async_event() - Process aynchronous events.
* @ha: SCSI driver HA context
@@ -714,21 +748,9 @@ skip_rio:
"%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
break;
case MBA_IDC_COMPLETE:
- DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
- "Complete -- %04x %04x %04x\n", vha->host_no, mb[1], mb[2],
- mb[3]));
- break;
case MBA_IDC_NOTIFY:
- DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
- "Request Notification -- %04x %04x %04x\n", vha->host_no,
- mb[1], mb[2], mb[3]));
- /**** Mailbox registers 4 - 7 valid!!! */
- break;
case MBA_IDC_TIME_EXT:
- DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
- "Time Extension -- %04x %04x %04x\n", vha->host_no, mb[1],
- mb[2], mb[3]));
- /**** Mailbox registers 4 - 7 valid!!! */
+ qla81xx_idc_event(vha, mb[0], mb[1]);
break;
}
@@ -1707,7 +1729,6 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
struct qla_hw_data *ha;
struct rsp_que *rsp;
struct device_reg_24xx __iomem *reg;
- uint16_t msix_disabled_hccr = 0;
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
@@ -1720,17 +1741,8 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
spin_lock_irq(&ha->hardware_lock);
- msix_disabled_hccr = rsp->options;
- if (!rsp->id)
- msix_disabled_hccr &= __constant_cpu_to_le32(BIT_22);
- else
- msix_disabled_hccr &= __constant_cpu_to_le32(BIT_6);
-
qla24xx_process_response_queue(rsp);
- if (!msix_disabled_hccr)
- WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
-
spin_unlock_irq(&ha->hardware_lock);
return IRQ_HANDLED;
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f94ffbb98e95..4c7504cb3990 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -3090,8 +3090,7 @@ verify_done:
}
int
-qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
- uint8_t options)
+qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
{
int rval;
unsigned long flags;
@@ -3101,7 +3100,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
struct qla_hw_data *ha = vha->hw;
mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
- mcp->mb[1] = options;
+ mcp->mb[1] = req->options;
mcp->mb[2] = MSW(LSD(req->dma));
mcp->mb[3] = LSW(LSD(req->dma));
mcp->mb[6] = MSW(MSD(req->dma));
@@ -3128,7 +3127,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
mcp->tov = 60;
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (!(options & BIT_0)) {
+ if (!(req->options & BIT_0)) {
WRT_REG_DWORD(&reg->req_q_in, 0);
WRT_REG_DWORD(&reg->req_q_out, 0);
}
@@ -3142,8 +3141,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
}
int
-qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
- uint8_t options)
+qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
{
int rval;
unsigned long flags;
@@ -3153,7 +3151,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
struct qla_hw_data *ha = vha->hw;
mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
- mcp->mb[1] = options;
+ mcp->mb[1] = rsp->options;
mcp->mb[2] = MSW(LSD(rsp->dma));
mcp->mb[3] = LSW(LSD(rsp->dma));
mcp->mb[6] = MSW(MSD(rsp->dma));
@@ -3178,7 +3176,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
mcp->tov = 60;
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (!(options & BIT_0)) {
+ if (!(rsp->options & BIT_0)) {
WRT_REG_DWORD(&reg->rsp_q_out, 0);
WRT_REG_DWORD(&reg->rsp_q_in, 0);
}
@@ -3193,3 +3191,29 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
return rval;
}
+int
+qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+ mcp->mb[0] = MBC_IDC_ACK;
+ memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
+ mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
+ vha->host_no, rval, mcp->mb[0]));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ }
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index f53179c46423..3f23932210c4 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -396,7 +396,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL);
- memset(vha->req_ques, 0, sizeof(vha->req_ques) * QLA_MAX_HOST_QUES);
+ memset(vha->req_ques, 0, sizeof(vha->req_ques));
vha->req_ques[0] = ha->req_q_map[0]->id;
host->can_queue = ha->req_q_map[0]->length + 128;
host->this_id = 255;
@@ -471,7 +471,7 @@ qla25xx_delete_req_que(struct scsi_qla_host *vha, struct req_que *req)
if (req) {
req->options |= BIT_0;
- ret = qla25xx_init_req_que(vha, req, req->options);
+ ret = qla25xx_init_req_que(vha, req);
}
if (ret == QLA_SUCCESS)
qla25xx_free_req_que(vha, req);
@@ -486,7 +486,7 @@ qla25xx_delete_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
if (rsp) {
rsp->options |= BIT_0;
- ret = qla25xx_init_rsp_que(vha, rsp, rsp->options);
+ ret = qla25xx_init_rsp_que(vha, rsp);
}
if (ret == QLA_SUCCESS)
qla25xx_free_rsp_que(vha, rsp);
@@ -502,7 +502,7 @@ int qla25xx_update_req_que(struct scsi_qla_host *vha, uint8_t que, uint8_t qos)
req->options |= BIT_3;
req->qos = qos;
- ret = qla25xx_init_req_que(vha, req, req->options);
+ ret = qla25xx_init_req_que(vha, req);
if (ret != QLA_SUCCESS)
DEBUG2_17(printk(KERN_WARNING "%s failed\n", __func__));
/* restore options bit */
@@ -632,7 +632,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->max_q_depth = ha->req_q_map[0]->max_q_depth;
mutex_unlock(&ha->vport_lock);
- ret = qla25xx_init_req_que(base_vha, req, options);
+ ret = qla25xx_init_req_que(base_vha, req);
if (ret != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
mutex_lock(&ha->vport_lock);
@@ -710,7 +710,7 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
if (ret)
goto que_failed;
- ret = qla25xx_init_rsp_que(base_vha, rsp, options);
+ ret = qla25xx_init_rsp_que(base_vha, rsp);
if (ret != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
mutex_lock(&ha->vport_lock);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index c11f872d3e10..2f5f72531e23 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -2522,6 +2522,19 @@ qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
return qla2x00_post_work(vha, e, 1);
}
+int
+qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
+{
+ struct qla_work_evt *e;
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK, 1);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
+ return qla2x00_post_work(vha, e, 1);
+}
+
static void
qla2x00_do_work(struct scsi_qla_host *vha)
{
@@ -2539,6 +2552,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
fc_host_post_event(vha->host, fc_get_event_number(),
e->u.aen.code, e->u.aen.data);
break;
+ case QLA_EVT_IDC_ACK:
+ qla81xx_idc_ack(vha, e->u.idc_ack.mb);
+ break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 9c3b694c049d..284827926eff 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -684,7 +684,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
"end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start,
le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)));
- switch (le32_to_cpu(region->code)) {
+ switch (le32_to_cpu(region->code) & 0xff) {
case FLT_REG_FW:
ha->flt_region_fw = start;
break;
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index cfa4c11a4797..79f7053da99b 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,7 +7,7 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.03.00-k2"
+#define QLA2XXX_VERSION "8.03.00-k3"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 3
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 66505bb79410..8f4de20c9deb 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -317,6 +317,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_gendev);
out:
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 8f0bd3f7a59f..516925d8b570 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1078,7 +1078,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
case BLKTRACESETUP:
return blk_trace_setup(sdp->device->request_queue,
sdp->disk->disk_name,
- sdp->device->sdev_gendev.devt,
+ MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
(char *)arg);
case BLKTRACESTART:
return blk_trace_startstop(sdp->device->request_queue, 1);
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 0d934bfbdd9b..b4b39811b445 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2083,6 +2083,20 @@ static int serial8250_startup(struct uart_port *port)
serial8250_set_mctrl(&up->port, up->port.mctrl);
+ /* Serial over Lan (SoL) hack:
+ Intel 8257x Gigabit ethernet chips have a
+ 16550 emulation, to be used for Serial Over Lan.
+ Those chips take a longer time than a normal
+ serial device to signalize that a transmission
+ data was queued. Due to that, the above test generally
+ fails. One solution would be to delay the reading of
+ iir. However, this is not reliable, since the timeout
+ is variable. So, let's just don't test if we receive
+ TX irq. This way, we'll never enable UART_BUG_TXEN.
+ */
+ if (up->port.flags & UPF_NO_TXEN_TEST)
+ goto dont_test_tx_en;
+
/*
* Do a quick test to see if we receive an
* interrupt when we enable the TX irq.
@@ -2102,6 +2116,7 @@ static int serial8250_startup(struct uart_port *port)
up->bugs &= ~UART_BUG_TXEN;
}
+dont_test_tx_en:
spin_unlock_irqrestore(&up->port.lock, flags);
/*
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index 536d8e510f66..533f82025adf 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -798,6 +798,21 @@ pci_default_setup(struct serial_private *priv,
return setup_port(priv, port, bar, offset, board->reg_shift);
}
+static int skip_tx_en_setup(struct serial_private *priv,
+ const struct pciserial_board *board,
+ struct uart_port *port, int idx)
+{
+ port->flags |= UPF_NO_TXEN_TEST;
+ printk(KERN_DEBUG "serial8250: skipping TxEn test for device "
+ "[%04x:%04x] subsystem [%04x:%04x]\n",
+ priv->dev->vendor,
+ priv->dev->device,
+ priv->dev->subsystem_vendor,
+ priv->dev->subsystem_device);
+
+ return pci_default_setup(priv, board, port, idx);
+}
+
/* This should be in linux/pci_ids.h */
#define PCI_VENDOR_ID_SBSMODULARIO 0x124B
#define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B
@@ -864,6 +879,27 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
.init = pci_inteli960ni_init,
.setup = pci_default_setup,
},
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_8257X_SOL,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = skip_tx_en_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82573L_SOL,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = skip_tx_en_setup,
+ },
+ {
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82573E_SOL,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ .setup = skip_tx_en_setup,
+ },
/*
* ITE
*/
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 89362d733d62..8f58f7ff0dd7 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -877,6 +877,10 @@ static int atmel_startup(struct uart_port *port)
}
}
+ /* Save current CSR for comparison in atmel_tasklet_func() */
+ atmel_port->irq_status_prev = UART_GET_CSR(port);
+ atmel_port->irq_status = atmel_port->irq_status_prev;
+
/*
* Finally, enable the serial port
*/
diff --git a/drivers/serial/jsm/jsm_driver.c b/drivers/serial/jsm/jsm_driver.c
index 92187e28608a..ac79cbe4c2cf 100644
--- a/drivers/serial/jsm/jsm_driver.c
+++ b/drivers/serial/jsm/jsm_driver.c
@@ -84,6 +84,8 @@ static int jsm_probe_one(struct pci_dev *pdev, const struct pci_device_id *ent)
brd->pci_dev = pdev;
if (pdev->device == PCIE_DEVICE_ID_NEO_4_IBM)
brd->maxports = 4;
+ else if (pdev->device == PCI_DEVICE_ID_DIGI_NEO_8)
+ brd->maxports = 8;
else
brd->maxports = 2;
@@ -212,6 +214,7 @@ static struct pci_device_id jsm_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45), 0, 0, 2 },
{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_NEO_2RJ45PRI), 0, 0, 3 },
{ PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_4_IBM), 0, 0, 4 },
+ { PCI_DEVICE(PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_NEO_8), 0, 0, 5 },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, jsm_pci_tbl);
diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c
index 49698cabc30d..f5ed9721aabb 100644
--- a/drivers/spi/spi_gpio.c
+++ b/drivers/spi/spi_gpio.c
@@ -114,7 +114,7 @@ static inline void setmosi(const struct spi_device *spi, int is_on)
static inline int getmiso(const struct spi_device *spi)
{
- return gpio_get_value(SPI_MISO_GPIO);
+ return !!gpio_get_value(SPI_MISO_GPIO);
}
#undef pdata
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index c54fc40458b1..a4301dc02d27 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -298,19 +298,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message)
EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend);
/**
- * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled
- * @dev: USB Host Controller being resumed
- *
- * Store this function in the HCD's struct pci_driver as .resume_early.
- */
-int usb_hcd_pci_resume_early(struct pci_dev *dev)
-{
- pci_restore_state(dev);
- return 0;
-}
-EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early);
-
-/**
* usb_hcd_pci_resume - power management resume of a PCI-based HCD
* @dev: USB Host Controller being resumed
*
@@ -333,6 +320,8 @@ int usb_hcd_pci_resume(struct pci_dev *dev)
}
#endif
+ pci_restore_state(dev);
+
hcd = pci_get_drvdata(dev);
if (hcd->state != HC_STATE_SUSPENDED) {
dev_dbg(hcd->self.controller,
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 5b94a56bec23..f750eb1ab595 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -257,7 +257,6 @@ extern void usb_hcd_pci_remove(struct pci_dev *dev);
#ifdef CONFIG_PM
extern int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t msg);
-extern int usb_hcd_pci_resume_early(struct pci_dev *dev);
extern int usb_hcd_pci_resume(struct pci_dev *dev);
#endif /* CONFIG_PM */
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
index 9b36205c5759..0ce4e2819847 100644
--- a/drivers/usb/gadget/pxa25x_udc.c
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -904,8 +904,8 @@ static void pxa25x_ep_fifo_flush(struct usb_ep *_ep)
/* most IN status is the same, but ISO can't stall */
*ep->reg_udccs = UDCCS_BI_TPC|UDCCS_BI_FTF|UDCCS_BI_TUR
- | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC)
- ? 0 : UDCCS_BI_SST;
+ | (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC
+ ? 0 : UDCCS_BI_SST);
}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index bb21fb0a4969..abb9a7706ec7 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -432,7 +432,6 @@ static struct pci_driver ehci_pci_driver = {
#ifdef CONFIG_PM
.suspend = usb_hcd_pci_suspend,
- .resume_early = usb_hcd_pci_resume_early,
.resume = usb_hcd_pci_resume,
#endif
.shutdown = usb_hcd_pci_shutdown,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 5d625c3fd423..f9961b4c0da3 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -487,7 +487,6 @@ static struct pci_driver ohci_pci_driver = {
#ifdef CONFIG_PM
.suspend = usb_hcd_pci_suspend,
- .resume_early = usb_hcd_pci_resume_early,
.resume = usb_hcd_pci_resume,
#endif
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 944f7e0ca4df..cf5e4cf7ea42 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -942,7 +942,6 @@ static struct pci_driver uhci_pci_driver = {
#ifdef CONFIG_PM
.suspend = usb_hcd_pci_suspend,
- .resume_early = usb_hcd_pci_resume_early,
.resume = usb_hcd_pci_resume,
#endif /* PM */
};
diff --git a/drivers/usb/host/whci/asl.c b/drivers/usb/host/whci/asl.c
index 2291c5f5af51..958751ccea43 100644
--- a/drivers/usb/host/whci/asl.c
+++ b/drivers/usb/host/whci/asl.c
@@ -227,13 +227,13 @@ void scan_async_work(struct work_struct *work)
* Now that the ASL is updated, complete the removal of any
* removed qsets.
*/
- spin_lock(&whc->lock);
+ spin_lock_irq(&whc->lock);
list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) {
qset_remove_complete(whc, qset);
}
- spin_unlock(&whc->lock);
+ spin_unlock_irq(&whc->lock);
}
/**
diff --git a/drivers/usb/host/whci/pzl.c b/drivers/usb/host/whci/pzl.c
index 7dc85a0bee7c..df8b85f07092 100644
--- a/drivers/usb/host/whci/pzl.c
+++ b/drivers/usb/host/whci/pzl.c
@@ -255,13 +255,13 @@ void scan_periodic_work(struct work_struct *work)
* Now that the PZL is updated, complete the removal of any
* removed qsets.
*/
- spin_lock(&whc->lock);
+ spin_lock_irq(&whc->lock);
list_for_each_entry_safe(qset, t, &whc->periodic_removed_list, list_node) {
qset_remove_complete(whc, qset);
}
- spin_unlock(&whc->lock);
+ spin_unlock_irq(&whc->lock);
}
/**
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index bf0af660df8a..fb19803060cf 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1054,10 +1054,7 @@ config FB_RIVA_BACKLIGHT
config FB_I810
tristate "Intel 810/815 support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PCI && X86_32
- select AGP
- select AGP_INTEL
- select FB
+ depends on EXPERIMENTAL && FB && PCI && X86_32 && AGP_INTEL
select FB_MODE_HELPERS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
@@ -1120,10 +1117,7 @@ config FB_CARILLO_RANCH
config FB_INTEL
tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && PCI && X86
- select FB
- select AGP
- select AGP_INTEL
+ depends on EXPERIMENTAL && FB && PCI && X86 && AGP_INTEL
select FB_MODE_HELPERS
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
diff --git a/drivers/video/atafb.c b/drivers/video/atafb.c
index 8058572a7428..018850c116c6 100644
--- a/drivers/video/atafb.c
+++ b/drivers/video/atafb.c
@@ -841,7 +841,7 @@ static int tt_detect(void)
tt_dmasnd.ctrl = DMASND_CTRL_OFF;
udelay(20); /* wait a while for things to settle down */
}
- mono_moni = (mfp.par_dt_reg & 0x80) == 0;
+ mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
tt_get_par(&par);
tt_encode_var(&atafb_predefined[0], &par);
@@ -2035,7 +2035,7 @@ static int stste_detect(void)
tt_dmasnd.ctrl = DMASND_CTRL_OFF;
udelay(20); /* wait a while for things to settle down */
}
- mono_moni = (mfp.par_dt_reg & 0x80) == 0;
+ mono_moni = (st_mfp.par_dt_reg & 0x80) == 0;
stste_get_par(&par);
stste_encode_var(&atafb_predefined[0], &par);
@@ -2086,20 +2086,20 @@ static void st_ovsc_switch(void)
return;
local_irq_save(flags);
- mfp.tim_ct_b = 0x10;
- mfp.active_edge |= 8;
- mfp.tim_ct_b = 0;
- mfp.tim_dt_b = 0xf0;
- mfp.tim_ct_b = 8;
- while (mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
+ st_mfp.tim_ct_b = 0x10;
+ st_mfp.active_edge |= 8;
+ st_mfp.tim_ct_b = 0;
+ st_mfp.tim_dt_b = 0xf0;
+ st_mfp.tim_ct_b = 8;
+ while (st_mfp.tim_dt_b > 1) /* TOS does it this way, don't ask why */
;
- new = mfp.tim_dt_b;
+ new = st_mfp.tim_dt_b;
do {
udelay(LINE_DELAY);
old = new;
- new = mfp.tim_dt_b;
+ new = st_mfp.tim_dt_b;
} while (old != new);
- mfp.tim_ct_b = 0x10;
+ st_mfp.tim_ct_b = 0x10;
udelay(SYNC_DELAY);
if (atari_switches & ATARI_SWITCH_OVSC_IKBD)
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
index e6e299feb51b..2181ce4d7ebd 100644
--- a/drivers/video/aty/aty128fb.c
+++ b/drivers/video/aty/aty128fb.c
@@ -2365,7 +2365,6 @@ static void fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx
static void aty128_set_suspend(struct aty128fb_par *par, int suspend)
{
u32 pmgt;
- u16 pwr_command;
struct pci_dev *pdev = par->pdev;
if (!par->pm_reg)
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 09a3d5522b43..325c10ff6a2c 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -406,7 +406,7 @@ config ITCO_WDT
---help---
Hardware driver for the intel TCO timer based watchdog devices.
These drivers are included in the Intel 82801 I/O Controller
- Hub family (from ICH0 up to ICH8) and in the Intel 6300ESB
+ Hub family (from ICH0 up to ICH10) and in the Intel 63xxESB
controller hub.
The TCO (Total Cost of Ownership) timer is a watchdog timer
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index 5531691f46ea..e35d54589232 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -107,10 +107,10 @@ static int at91_wdt_close(struct inode *inode, struct file *file)
static int at91_wdt_settimeout(int new_time)
{
/*
- * All counting occurs at SLOW_CLOCK / 128 = 0.256 Hz
+ * All counting occurs at SLOW_CLOCK / 128 = 256 Hz
*
* Since WDV is a 16-bit counter, the maximum period is
- * 65536 / 0.256 = 256 seconds.
+ * 65536 / 256 = 256 seconds.
*/
if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
return -EINVAL;
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index b1da287f90ec..a56ac84381b1 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -18,6 +18,7 @@
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/init.h>
+#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c
index 2474ebca88f6..d8264ad0be41 100644
--- a/drivers/watchdog/iTCO_vendor_support.c
+++ b/drivers/watchdog/iTCO_vendor_support.c
@@ -1,7 +1,7 @@
/*
* intel TCO vendor specific watchdog driver support
*
- * (c) Copyright 2006-2008 Wim Van Sebroeck <wim@iguana.be>.
+ * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -19,7 +19,7 @@
/* Module and version information */
#define DRV_NAME "iTCO_vendor_support"
-#define DRV_VERSION "1.02"
+#define DRV_VERSION "1.03"
#define PFX DRV_NAME ": "
/* Includes */
@@ -77,6 +77,26 @@ MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (n
* 20.6 seconds.
*/
+static void supermicro_old_pre_start(unsigned long acpibase)
+{
+ unsigned long val32;
+
+ /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
+ val32 = inl(SMI_EN);
+ val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
+ outl(val32, SMI_EN); /* Needed to activate watchdog */
+}
+
+static void supermicro_old_pre_stop(unsigned long acpibase)
+{
+ unsigned long val32;
+
+ /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
+ val32 = inl(SMI_EN);
+ val32 |= 0x00002000; /* Turn on SMI clearing watchdog */
+ outl(val32, SMI_EN); /* Needed to deactivate watchdog */
+}
+
static void supermicro_old_pre_keepalive(unsigned long acpibase)
{
/* Reload TCO Timer (done in iTCO_wdt_keepalive) + */
@@ -228,14 +248,18 @@ static void supermicro_new_pre_set_heartbeat(unsigned int heartbeat)
void iTCO_vendor_pre_start(unsigned long acpibase,
unsigned int heartbeat)
{
- if (vendorsupport == SUPERMICRO_NEW_BOARD)
+ if (vendorsupport == SUPERMICRO_OLD_BOARD)
+ supermicro_old_pre_start(acpibase);
+ else if (vendorsupport == SUPERMICRO_NEW_BOARD)
supermicro_new_pre_start(heartbeat);
}
EXPORT_SYMBOL(iTCO_vendor_pre_start);
void iTCO_vendor_pre_stop(unsigned long acpibase)
{
- if (vendorsupport == SUPERMICRO_NEW_BOARD)
+ if (vendorsupport == SUPERMICRO_OLD_BOARD)
+ supermicro_old_pre_stop(acpibase);
+ else if (vendorsupport == SUPERMICRO_NEW_BOARD)
supermicro_new_pre_stop();
}
EXPORT_SYMBOL(iTCO_vendor_pre_stop);
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 5b395a4ddfdf..352334947ea3 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -1,7 +1,7 @@
/*
- * intel TCO Watchdog Driver (Used in i82801 and i6300ESB chipsets)
+ * intel TCO Watchdog Driver (Used in i82801 and i63xxESB chipsets)
*
- * (c) Copyright 2006-2008 Wim Van Sebroeck <wim@iguana.be>.
+ * (c) Copyright 2006-2009 Wim Van Sebroeck <wim@iguana.be>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -63,7 +63,7 @@
/* Module and version information */
#define DRV_NAME "iTCO_wdt"
-#define DRV_VERSION "1.04"
+#define DRV_VERSION "1.05"
#define PFX DRV_NAME ": "
/* Includes */
@@ -236,16 +236,16 @@ MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
/* Address definitions for the TCO */
/* TCO base address */
-#define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60
+#define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60
/* SMI Control and Enable Register */
-#define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30
+#define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30
#define TCO_RLD TCOBASE + 0x00 /* TCO Timer Reload and Curr. Value */
#define TCOv1_TMR TCOBASE + 0x01 /* TCOv1 Timer Initial Value */
-#define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */
-#define TCO_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */
-#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
-#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */
+#define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */
+#define TCO_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */
+#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */
+#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */
#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */
#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */
#define TCOv2_TMR TCOBASE + 0x12 /* TCOv2 Timer Initial Value */
@@ -338,7 +338,6 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void)
static int iTCO_wdt_start(void)
{
unsigned int val;
- unsigned long val32;
spin_lock(&iTCO_wdt_private.io_lock);
@@ -351,11 +350,6 @@ static int iTCO_wdt_start(void)
return -EIO;
}
- /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
- val32 = inl(SMI_EN);
- val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
- outl(val32, SMI_EN);
-
/* Force the timer to its reload value by writing to the TCO_RLD
register */
if (iTCO_wdt_private.iTCO_version == 2)
@@ -378,7 +372,6 @@ static int iTCO_wdt_start(void)
static int iTCO_wdt_stop(void)
{
unsigned int val;
- unsigned long val32;
spin_lock(&iTCO_wdt_private.io_lock);
@@ -390,11 +383,6 @@ static int iTCO_wdt_stop(void)
outw(val, TCO1_CNT);
val = inw(TCO1_CNT);
- /* Bit 13: TCO_EN -> 1 = Enables the TCO logic to generate SMI# */
- val32 = inl(SMI_EN);
- val32 |= 0x00002000;
- outl(val32, SMI_EN);
-
/* Set the NO_REBOOT bit to prevent later reboots, just for sure */
iTCO_wdt_set_NO_REBOOT_bit();
@@ -649,6 +637,7 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
int ret;
u32 base_address;
unsigned long RCBA;
+ unsigned long val32;
/*
* Find the ACPI/PM base I/O address which is the base
@@ -695,6 +684,10 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev,
ret = -EIO;
goto out;
}
+ /* Bit 13: TCO_EN -> 0 = Disables TCO logic generating an SMI# */
+ val32 = inl(SMI_EN);
+ val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */
+ outl(val32, SMI_EN);
/* The TCO I/O registers reside in a 32-byte range pointed to
by the TCOBASE value */
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c
index e7e83b65c18f..3ccd348d112d 100644
--- a/drivers/xen/manage.c
+++ b/drivers/xen/manage.c
@@ -45,6 +45,13 @@ static int xen_suspend(void *data)
err);
return err;
}
+ err = sysdev_suspend(PMSG_SUSPEND);
+ if (err) {
+ printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
+ err);
+ device_power_up(PMSG_RESUME);
+ return err;
+ }
xen_mm_pin_all();
gnttab_suspend();
@@ -61,6 +68,7 @@ static int xen_suspend(void *data)
gnttab_resume();
xen_mm_unpin_all();
+ sysdev_resume();
device_power_up(PMSG_RESUME);
if (!*cancelled) {
diff --git a/fs/bio.c b/fs/bio.c
index 062299acbccd..72ab251cdb9c 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -302,9 +302,10 @@ void bio_init(struct bio *bio)
struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
{
struct bio *bio = NULL;
+ void *p;
if (bs) {
- void *p = mempool_alloc(bs->bio_pool, gfp_mask);
+ p = mempool_alloc(bs->bio_pool, gfp_mask);
if (p)
bio = p + bs->front_pad;
@@ -329,7 +330,7 @@ struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs)
}
if (unlikely(!bvl)) {
if (bs)
- mempool_free(bio, bs->bio_pool);
+ mempool_free(p, bs->bio_pool);
else
kfree(bio);
bio = NULL;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 35443cc4b9a9..42491d728e99 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -38,19 +38,12 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root,
struct btrfs_path *path, int level, int slot);
-inline void btrfs_init_path(struct btrfs_path *p)
-{
- memset(p, 0, sizeof(*p));
-}
-
struct btrfs_path *btrfs_alloc_path(void)
{
struct btrfs_path *path;
- path = kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS);
- if (path) {
- btrfs_init_path(path);
+ path = kmem_cache_zalloc(btrfs_path_cachep, GFP_NOFS);
+ if (path)
path->reada = 1;
- }
return path;
}
@@ -69,14 +62,38 @@ noinline void btrfs_set_path_blocking(struct btrfs_path *p)
/*
* reset all the locked nodes in the patch to spinning locks.
+ *
+ * held is used to keep lockdep happy, when lockdep is enabled
+ * we set held to a blocking lock before we go around and
+ * retake all the spinlocks in the path. You can safely use NULL
+ * for held
*/
-noinline void btrfs_clear_path_blocking(struct btrfs_path *p)
+noinline void btrfs_clear_path_blocking(struct btrfs_path *p,
+ struct extent_buffer *held)
{
int i;
- for (i = 0; i < BTRFS_MAX_LEVEL; i++) {
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ /* lockdep really cares that we take all of these spinlocks
+ * in the right order. If any of the locks in the path are not
+ * currently blocking, it is going to complain. So, make really
+ * really sure by forcing the path to blocking before we clear
+ * the path blocking.
+ */
+ if (held)
+ btrfs_set_lock_blocking(held);
+ btrfs_set_path_blocking(p);
+#endif
+
+ for (i = BTRFS_MAX_LEVEL - 1; i >= 0; i--) {
if (p->nodes[i] && p->locks[i])
btrfs_clear_lock_blocking(p->nodes[i]);
}
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+ if (held)
+ btrfs_clear_lock_blocking(held);
+#endif
}
/* this also releases the path */
@@ -286,7 +303,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
trans->transid, level, &ins);
BUG_ON(ret);
cow = btrfs_init_new_buffer(trans, root, prealloc_dest,
- buf->len);
+ buf->len, level);
} else {
cow = btrfs_alloc_free_block(trans, root, buf->len,
parent_start,
@@ -917,9 +934,9 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
/* promote the child to a root */
child = read_node_slot(root, mid, 0);
+ BUG_ON(!child);
btrfs_tree_lock(child);
btrfs_set_lock_blocking(child);
- BUG_ON(!child);
ret = btrfs_cow_block(trans, root, child, mid, 0, &child, 0);
BUG_ON(ret);
@@ -1566,7 +1583,7 @@ cow_done:
if (!p->skip_locking)
p->locks[level] = 1;
- btrfs_clear_path_blocking(p);
+ btrfs_clear_path_blocking(p, NULL);
/*
* we have a lock on b and as long as we aren't changing
@@ -1605,7 +1622,7 @@ cow_done:
btrfs_set_path_blocking(p);
sret = split_node(trans, root, p, level);
- btrfs_clear_path_blocking(p);
+ btrfs_clear_path_blocking(p, NULL);
BUG_ON(sret > 0);
if (sret) {
@@ -1625,7 +1642,7 @@ cow_done:
btrfs_set_path_blocking(p);
sret = balance_level(trans, root, p, level);
- btrfs_clear_path_blocking(p);
+ btrfs_clear_path_blocking(p, NULL);
if (sret) {
ret = sret;
@@ -1688,13 +1705,13 @@ cow_done:
if (!p->skip_locking) {
int lret;
- btrfs_clear_path_blocking(p);
+ btrfs_clear_path_blocking(p, NULL);
lret = btrfs_try_spin_lock(b);
if (!lret) {
btrfs_set_path_blocking(p);
btrfs_tree_lock(b);
- btrfs_clear_path_blocking(p);
+ btrfs_clear_path_blocking(p, b);
}
}
} else {
@@ -1706,7 +1723,7 @@ cow_done:
btrfs_set_path_blocking(p);
sret = split_leaf(trans, root, key,
p, ins_len, ret == 0);
- btrfs_clear_path_blocking(p);
+ btrfs_clear_path_blocking(p, NULL);
BUG_ON(sret > 0);
if (sret) {
@@ -3926,7 +3943,6 @@ find_next_key:
btrfs_release_path(root, path);
goto again;
} else {
- btrfs_clear_path_blocking(path);
goto out;
}
}
@@ -3946,7 +3962,7 @@ find_next_key:
path->locks[level - 1] = 1;
path->nodes[level - 1] = cur;
unlock_up(path, level, 1);
- btrfs_clear_path_blocking(path);
+ btrfs_clear_path_blocking(path, NULL);
}
out:
if (ret == 0)
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 531db112c8bd..766b31ae3186 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -43,11 +43,7 @@ struct btrfs_ordered_sum;
#define BTRFS_ACL_NOT_CACHED ((void *)-1)
-#ifdef CONFIG_LOCKDEP
-# define BTRFS_MAX_LEVEL 7
-#else
-# define BTRFS_MAX_LEVEL 8
-#endif
+#define BTRFS_MAX_LEVEL 8
/* holds pointers to all of the tree roots */
#define BTRFS_ROOT_TREE_OBJECTID 1ULL
@@ -1715,7 +1711,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
u64 empty_size);
struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
- u64 bytenr, u32 blocksize);
+ u64 bytenr, u32 blocksize,
+ int level);
int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
u64 num_bytes, u64 parent, u64 min_bytes,
@@ -1834,9 +1831,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
void btrfs_release_path(struct btrfs_root *root, struct btrfs_path *p);
struct btrfs_path *btrfs_alloc_path(void);
void btrfs_free_path(struct btrfs_path *p);
-void btrfs_init_path(struct btrfs_path *p);
void btrfs_set_path_blocking(struct btrfs_path *p);
-void btrfs_clear_path_blocking(struct btrfs_path *p);
void btrfs_unlock_up_safe(struct btrfs_path *p, int level);
int btrfs_del_items(struct btrfs_trans_handle *trans, struct btrfs_root *root,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5aebddd71193..adda739a0215 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -75,6 +75,40 @@ struct async_submit_bio {
struct btrfs_work work;
};
+/* These are used to set the lockdep class on the extent buffer locks.
+ * The class is set by the readpage_end_io_hook after the buffer has
+ * passed csum validation but before the pages are unlocked.
+ *
+ * The lockdep class is also set by btrfs_init_new_buffer on freshly
+ * allocated blocks.
+ *
+ * The class is based on the level in the tree block, which allows lockdep
+ * to know that lower nodes nest inside the locks of higher nodes.
+ *
+ * We also add a check to make sure the highest level of the tree is
+ * the same as our lockdep setup here. If BTRFS_MAX_LEVEL changes, this
+ * code needs update as well.
+ */
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+# if BTRFS_MAX_LEVEL != 8
+# error
+# endif
+static struct lock_class_key btrfs_eb_class[BTRFS_MAX_LEVEL + 1];
+static const char *btrfs_eb_name[BTRFS_MAX_LEVEL + 1] = {
+ /* leaf */
+ "btrfs-extent-00",
+ "btrfs-extent-01",
+ "btrfs-extent-02",
+ "btrfs-extent-03",
+ "btrfs-extent-04",
+ "btrfs-extent-05",
+ "btrfs-extent-06",
+ "btrfs-extent-07",
+ /* highest possible level */
+ "btrfs-extent-08",
+};
+#endif
+
/*
* extents on the btree inode are pretty simple, there's one extent
* that covers the entire device
@@ -347,6 +381,15 @@ static int check_tree_block_fsid(struct btrfs_root *root,
return ret;
}
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level)
+{
+ lockdep_set_class_and_name(&eb->lock,
+ &btrfs_eb_class[level],
+ btrfs_eb_name[level]);
+}
+#endif
+
static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
struct extent_state *state)
{
@@ -392,6 +435,8 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
}
found_level = btrfs_header_level(eb);
+ btrfs_set_buffer_lockdep_class(eb, found_level);
+
ret = csum_tree_block(root, eb, 1);
if (ret)
ret = -EIO;
@@ -1777,7 +1822,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
ret = find_and_setup_root(tree_root, fs_info,
BTRFS_DEV_TREE_OBJECTID, dev_root);
dev_root->track_dirty = 1;
-
if (ret)
goto fail_extent_root;
diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h
index 494a56eb2986..95029db227be 100644
--- a/fs/btrfs/disk-io.h
+++ b/fs/btrfs/disk-io.h
@@ -101,4 +101,14 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
struct btrfs_root *root);
int btree_lock_page_hook(struct page *page);
+
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb, int level);
+#else
+static inline void btrfs_set_buffer_lockdep_class(struct extent_buffer *eb,
+ int level)
+{
+}
+#endif
#endif
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7527523c2d2d..0a5d796c9f7e 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1323,8 +1323,25 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
struct btrfs_root *root)
{
- finish_current_insert(trans, root->fs_info->extent_root, 1);
- del_pending_extents(trans, root->fs_info->extent_root, 1);
+ u64 start;
+ u64 end;
+ int ret;
+
+ while(1) {
+ finish_current_insert(trans, root->fs_info->extent_root, 1);
+ del_pending_extents(trans, root->fs_info->extent_root, 1);
+
+ /* is there more work to do? */
+ ret = find_first_extent_bit(&root->fs_info->pending_del,
+ 0, &start, &end, EXTENT_WRITEBACK);
+ if (!ret)
+ continue;
+ ret = find_first_extent_bit(&root->fs_info->extent_ins,
+ 0, &start, &end, EXTENT_WRITEBACK);
+ if (!ret)
+ continue;
+ break;
+ }
return 0;
}
@@ -2211,13 +2228,12 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
u64 end;
u64 priv;
u64 search = 0;
- u64 skipped = 0;
struct btrfs_fs_info *info = extent_root->fs_info;
struct btrfs_path *path;
struct pending_extent_op *extent_op, *tmp;
struct list_head insert_list, update_list;
int ret;
- int num_inserts = 0, max_inserts;
+ int num_inserts = 0, max_inserts, restart = 0;
path = btrfs_alloc_path();
INIT_LIST_HEAD(&insert_list);
@@ -2233,19 +2249,19 @@ again:
ret = find_first_extent_bit(&info->extent_ins, search, &start,
&end, EXTENT_WRITEBACK);
if (ret) {
- if (skipped && all && !num_inserts &&
+ if (restart && !num_inserts &&
list_empty(&update_list)) {
- skipped = 0;
+ restart = 0;
search = 0;
continue;
}
- mutex_unlock(&info->extent_ins_mutex);
break;
}
ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS);
if (!ret) {
- skipped = 1;
+ if (all)
+ restart = 1;
search = end + 1;
if (need_resched()) {
mutex_unlock(&info->extent_ins_mutex);
@@ -2264,7 +2280,7 @@ again:
list_add_tail(&extent_op->list, &insert_list);
search = end + 1;
if (num_inserts == max_inserts) {
- mutex_unlock(&info->extent_ins_mutex);
+ restart = 1;
break;
}
} else if (extent_op->type == PENDING_BACKREF_UPDATE) {
@@ -2280,7 +2296,6 @@ again:
* somebody marked this thing for deletion then just unlock it and be
* done, the free_extents will handle it
*/
- mutex_lock(&info->extent_ins_mutex);
list_for_each_entry_safe(extent_op, tmp, &update_list, list) {
clear_extent_bits(&info->extent_ins, extent_op->bytenr,
extent_op->bytenr + extent_op->num_bytes - 1,
@@ -2302,6 +2317,10 @@ again:
if (!list_empty(&update_list)) {
ret = update_backrefs(trans, extent_root, path, &update_list);
BUG_ON(ret);
+
+ /* we may have COW'ed new blocks, so lets start over */
+ if (all)
+ restart = 1;
}
/*
@@ -2309,9 +2328,9 @@ again:
* need to make sure everything is cleaned then reset everything and
* go back to the beginning
*/
- if (!num_inserts && all && skipped) {
+ if (!num_inserts && restart) {
search = 0;
- skipped = 0;
+ restart = 0;
INIT_LIST_HEAD(&update_list);
INIT_LIST_HEAD(&insert_list);
goto again;
@@ -2368,27 +2387,19 @@ again:
BUG_ON(ret);
/*
- * if we broke out of the loop in order to insert stuff because we hit
- * the maximum number of inserts at a time we can handle, then loop
- * back and pick up where we left off
+ * if restart is set for whatever reason we need to go back and start
+ * searching through the pending list again.
+ *
+ * We just inserted some extents, which could have resulted in new
+ * blocks being allocated, which would result in new blocks needing
+ * updates, so if all is set we _must_ restart to get the updated
+ * blocks.
*/
- if (num_inserts == max_inserts) {
- INIT_LIST_HEAD(&insert_list);
- INIT_LIST_HEAD(&update_list);
- num_inserts = 0;
- goto again;
- }
-
- /*
- * again, if we need to make absolutely sure there are no more pending
- * extent operations left and we know that we skipped some, go back to
- * the beginning and do it all again
- */
- if (all && skipped) {
+ if (restart || all) {
INIT_LIST_HEAD(&insert_list);
INIT_LIST_HEAD(&update_list);
search = 0;
- skipped = 0;
+ restart = 0;
num_inserts = 0;
goto again;
}
@@ -2709,6 +2720,8 @@ again:
goto again;
}
+ if (!err)
+ finish_current_insert(trans, extent_root, 0);
return err;
}
@@ -2859,7 +2872,8 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
if (data & BTRFS_BLOCK_GROUP_METADATA) {
last_ptr = &root->fs_info->last_alloc;
- empty_cluster = 64 * 1024;
+ if (!btrfs_test_opt(root, SSD))
+ empty_cluster = 64 * 1024;
}
if ((data & BTRFS_BLOCK_GROUP_DATA) && btrfs_test_opt(root, SSD))
@@ -3402,7 +3416,8 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans,
struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
struct btrfs_root *root,
- u64 bytenr, u32 blocksize)
+ u64 bytenr, u32 blocksize,
+ int level)
{
struct extent_buffer *buf;
@@ -3410,6 +3425,7 @@ struct extent_buffer *btrfs_init_new_buffer(struct btrfs_trans_handle *trans,
if (!buf)
return ERR_PTR(-ENOMEM);
btrfs_set_header_generation(buf, trans->transid);
+ btrfs_set_buffer_lockdep_class(buf, level);
btrfs_tree_lock(buf);
clean_tree_block(trans, root, buf);
@@ -3453,7 +3469,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans,
return ERR_PTR(ret);
}
- buf = btrfs_init_new_buffer(trans, root, ins.objectid, blocksize);
+ buf = btrfs_init_new_buffer(trans, root, ins.objectid,
+ blocksize, level);
return buf;
}
@@ -5641,7 +5658,9 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root,
prev_block = block_start;
}
+ mutex_lock(&extent_root->fs_info->trans_mutex);
btrfs_record_root_in_trans(found_root);
+ mutex_unlock(&extent_root->fs_info->trans_mutex);
if (ref_path->owner_objectid >= BTRFS_FIRST_FREE_OBJECTID) {
/*
* try to update data extent references while
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 37d43b516b79..ebe6b29e6069 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -415,8 +415,6 @@ static int split_state(struct extent_io_tree *tree, struct extent_state *orig,
node = tree_insert(&tree->state, prealloc->end, &prealloc->rb_node);
if (node) {
- struct extent_state *found;
- found = rb_entry(node, struct extent_state, rb_node);
free_extent_state(prealloc);
return -EEXIST;
}
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 3e8023efaff7..872f104576e5 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1222,7 +1222,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
/*
* ok we haven't committed the transaction yet, lets do a commit
*/
- if (file->private_data)
+ if (file && file->private_data)
btrfs_ioctl_trans_end(file);
trans = btrfs_start_transaction(root, 1);
@@ -1231,7 +1231,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
goto out;
}
- ret = btrfs_log_dentry_safe(trans, root, file->f_dentry);
+ ret = btrfs_log_dentry_safe(trans, root, dentry);
if (ret < 0)
goto out;
@@ -1245,7 +1245,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
* file again, but that will end up using the synchronization
* inside btrfs_sync_log to keep things safe.
*/
- mutex_unlock(&file->f_dentry->d_inode->i_mutex);
+ mutex_unlock(&dentry->d_inode->i_mutex);
if (ret > 0) {
ret = btrfs_commit_transaction(trans, root);
@@ -1253,7 +1253,7 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
btrfs_sync_log(trans, root);
ret = btrfs_end_transaction(trans, root);
}
- mutex_lock(&file->f_dentry->d_inode->i_mutex);
+ mutex_lock(&dentry->d_inode->i_mutex);
out:
return ret > 0 ? EIO : ret;
}
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c
index 2aa79873eb46..cc7334d833c9 100644
--- a/fs/btrfs/inode-map.c
+++ b/fs/btrfs/inode-map.c
@@ -84,7 +84,6 @@ int btrfs_find_free_objectid(struct btrfs_trans_handle *trans,
search_key.type = 0;
search_key.offset = 0;
- btrfs_init_path(path);
start_found = 0;
ret = btrfs_search_slot(trans, root, &search_key, path, 0, 0);
if (ret < 0)
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 8f0706210a47..3cee77ae03c8 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2531,8 +2531,6 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans,
key.offset = (u64)-1;
key.type = (u8)-1;
- btrfs_init_path(path);
-
search_again:
ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
if (ret < 0)
@@ -4263,7 +4261,7 @@ static int btrfs_releasepage(struct page *page, gfp_t gfp_flags)
{
if (PageWriteback(page) || PageDirty(page))
return 0;
- return __btrfs_releasepage(page, gfp_flags);
+ return __btrfs_releasepage(page, gfp_flags & GFP_NOFS);
}
static void btrfs_invalidatepage(struct page *page, unsigned long offset)
diff --git a/fs/btrfs/locking.c b/fs/btrfs/locking.c
index 9ebe9385129b..85506c4a3af7 100644
--- a/fs/btrfs/locking.c
+++ b/fs/btrfs/locking.c
@@ -25,21 +25,10 @@
#include "extent_io.h"
#include "locking.h"
-/*
- * btrfs_header_level() isn't free, so don't call it when lockdep isn't
- * on
- */
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-static inline void spin_nested(struct extent_buffer *eb)
-{
- spin_lock_nested(&eb->lock, BTRFS_MAX_LEVEL - btrfs_header_level(eb));
-}
-#else
static inline void spin_nested(struct extent_buffer *eb)
{
spin_lock(&eb->lock);
}
-#endif
/*
* Setting a lock to blocking will drop the spinlock and set the
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index f3fd7e2cbc38..19a4daf03ccb 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -379,7 +379,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
btrfs_start_delalloc_inodes(root);
btrfs_wait_ordered_extents(root, 0);
- btrfs_clean_old_snapshots(root);
trans = btrfs_start_transaction(root, 1);
ret = btrfs_commit_transaction(trans, root);
sb->s_dirt = 0;
@@ -511,6 +510,10 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
struct btrfs_root *root = btrfs_sb(sb);
int ret;
+ ret = btrfs_parse_options(root, data);
+ if (ret)
+ return -EINVAL;
+
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 919172de5c9a..4112d53d4f4d 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -688,7 +688,9 @@ static noinline int drop_dirty_roots(struct btrfs_root *tree_root,
num_bytes -= btrfs_root_used(&dirty->root->root_item);
bytes_used = btrfs_root_used(&root->root_item);
if (num_bytes) {
+ mutex_lock(&root->fs_info->trans_mutex);
btrfs_record_root_in_trans(root);
+ mutex_unlock(&root->fs_info->trans_mutex);
btrfs_set_root_used(&root->root_item,
bytes_used - num_bytes);
}
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 20794290256b..9c462fbd60fa 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2832,7 +2832,9 @@ again:
BUG_ON(!wc.replay_dest);
wc.replay_dest->log_root = log;
+ mutex_lock(&fs_info->trans_mutex);
btrfs_record_root_in_trans(wc.replay_dest);
+ mutex_unlock(&fs_info->trans_mutex);
ret = walk_log_tree(trans, log, &wc);
BUG_ON(ret);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index bcd14ebccae1..1316139bf9e8 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2894,10 +2894,6 @@ static int read_one_chunk(struct btrfs_root *root, struct btrfs_key *key,
free_extent_map(em);
}
- map = kzalloc(sizeof(*map), GFP_NOFS);
- if (!map)
- return -ENOMEM;
-
em = alloc_extent_map(GFP_NOFS);
if (!em)
return -ENOMEM;
@@ -3106,6 +3102,8 @@ int btrfs_read_sys_array(struct btrfs_root *root)
if (!sb)
return -ENOMEM;
btrfs_set_buffer_uptodate(sb);
+ btrfs_set_buffer_lockdep_class(sb, 0);
+
write_extent_buffer(sb, super_copy, 0, BTRFS_SUPER_INFO_SIZE);
array_size = btrfs_super_sys_array_size(super_copy);
diff --git a/fs/buffer.c b/fs/buffer.c
index 665d446b25bc..9f697419ed8e 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -777,6 +777,7 @@ static int __set_page_dirty(struct page *page,
__inc_zone_page_state(page, NR_FILE_DIRTY);
__inc_bdi_stat(mapping->backing_dev_info,
BDI_RECLAIMABLE);
+ task_dirty_inc(current);
task_io_account_write(PAGE_CACHE_SIZE);
}
radix_tree_tag_set(&mapping->page_tree,
@@ -3108,7 +3109,7 @@ int sync_dirty_buffer(struct buffer_head *bh)
if (test_clear_buffer_dirty(bh)) {
get_bh(bh);
bh->b_end_io = end_buffer_write_sync;
- ret = submit_bh(WRITE_SYNC, bh);
+ ret = submit_bh(WRITE, bh);
wait_on_buffer(bh);
if (buffer_eopnotsupp(bh)) {
clear_buffer_eopnotsupp(bh);
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES
index 73ac7ebd1dfc..851388fafc73 100644
--- a/fs/cifs/CHANGES
+++ b/fs/cifs/CHANGES
@@ -1,3 +1,13 @@
+Version 1.57
+------------
+Improve support for multiple security contexts to the same server. We
+used to use the same "vcnumber" for all connections which could cause
+the server to treat subsequent connections, especially those that
+are authenticated as guest, as reconnections, invalidating the earlier
+user's smb session. This fix allows cifs to mount multiple times to the
+same server with different userids without risking invalidating earlier
+established security contexts.
+
Version 1.56
------------
Add "forcemandatorylock" mount option to allow user to use mandatory
@@ -7,7 +17,10 @@ specified and user does not have access to query information about the
top of the share. Fix problem in 2.6.28 resolving DFS paths to
Samba servers (worked to Windows). Fix rmdir so that pending search
(readdir) requests do not get invalid results which include the now
-removed directory.
+removed directory. Fix oops in cifs_dfs_ref.c when prefixpath is not reachable
+when using DFS. Add better file create support to servers which support
+the CIFS POSIX protocol extensions (this adds support for new flags
+on create, and improves semantics for write of locked ranges).
Version 1.55
------------
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
index 7ac481841f87..2b1d28a9ee28 100644
--- a/fs/cifs/cifsfs.h
+++ b/fs/cifs/cifsfs.h
@@ -100,5 +100,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
extern const struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
-#define CIFS_VERSION "1.56"
+#define CIFS_VERSION "1.57"
#endif /* _CIFSFS_H */
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 94c1ca0ec953..e004f6db5fc8 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -164,9 +164,12 @@ struct TCP_Server_Info {
/* multiplexed reads or writes */
unsigned int maxBuf; /* maxBuf specifies the maximum */
/* message size the server can send or receive for non-raw SMBs */
- unsigned int maxRw; /* maxRw specifies the maximum */
+ unsigned int max_rw; /* maxRw specifies the maximum */
/* message size the server can send or receive for */
/* SMB_COM_WRITE_RAW or SMB_COM_READ_RAW. */
+ unsigned int max_vcs; /* maximum number of smb sessions, at least
+ those that can be specified uniquely with
+ vcnumbers */
char sessid[4]; /* unique token id for this session */
/* (returned on Negotiate */
int capabilities; /* allow selective disabling of caps by smb sess */
@@ -210,6 +213,7 @@ struct cifsSesInfo {
unsigned overrideSecFlg; /* if non-zero override global sec flags */
__u16 ipc_tid; /* special tid for connection to IPC share */
__u16 flags;
+ __u16 vcnum;
char *serverOS; /* name of operating system underlying server */
char *serverNOS; /* name of network operating system of server */
char *serverDomain; /* security realm of server */
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 382ba6298809..083dfc57c7a3 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -42,6 +42,7 @@ extern void _FreeXid(unsigned int);
#define GetXid() (int)_GetXid(); cFYI(1,("CIFS VFS: in %s as Xid: %d with uid: %d",__func__, xid,current_fsuid()));
#define FreeXid(curr_xid) {_FreeXid(curr_xid); cFYI(1,("CIFS VFS: leaving %s (xid = %d) rc = %d",__func__,curr_xid,(int)rc));}
extern char *build_path_from_dentry(struct dentry *);
+extern char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
/* extern void renew_parental_timestamps(struct dentry *direntry);*/
extern int SendReceive(const unsigned int /* xid */ , struct cifsSesInfo *,
@@ -91,6 +92,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec);
extern __le64 cnvrtDosCifsTm(__u16 date, __u16 time);
extern struct timespec cnvrtDosUnixTm(__u16 date, __u16 time);
+extern void posix_fill_in_inode(struct inode *tmp_inode,
+ FILE_UNIX_BASIC_INFO *pData, int isNewInode);
+extern struct inode *cifs_new_inode(struct super_block *sb, __u64 *inum);
extern int cifs_get_inode_info(struct inode **pinode,
const unsigned char *search_path,
FILE_ALL_INFO *pfile_info,
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index 552642a507c4..939e2f76b959 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -528,14 +528,15 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
server->maxReq = le16_to_cpu(rsp->MaxMpxCount);
server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize),
(__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
+ server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs);
GETU32(server->sessid) = le32_to_cpu(rsp->SessionKey);
/* even though we do not use raw we might as well set this
accurately, in case we ever find a need for it */
if ((le16_to_cpu(rsp->RawMode) & RAW_ENABLE) == RAW_ENABLE) {
- server->maxRw = 0xFF00;
+ server->max_rw = 0xFF00;
server->capabilities = CAP_MPX_MODE | CAP_RAW_MODE;
} else {
- server->maxRw = 0;/* we do not need to use raw anyway */
+ server->max_rw = 0;/* do not need to use raw anyway */
server->capabilities = CAP_MPX_MODE;
}
tmp = (__s16)le16_to_cpu(rsp->ServerTimeZone);
@@ -638,7 +639,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
/* probably no need to store and check maxvcs */
server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize),
(__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE);
- server->maxRw = le32_to_cpu(pSMBr->MaxRawSize);
+ server->max_rw = le32_to_cpu(pSMBr->MaxRawSize);
cFYI(DBG2, ("Max buf = %d", ses->server->maxBuf));
GETU32(ses->server->sessid) = le32_to_cpu(pSMBr->SessionKey);
server->capabilities = le32_to_cpu(pSMBr->Capabilities);
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 2209be943051..da0f4ffa0613 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -23,7 +23,6 @@
#include <linux/string.h>
#include <linux/list.h>
#include <linux/wait.h>
-#include <linux/ipv6.h>
#include <linux/pagemap.h>
#include <linux/ctype.h>
#include <linux/utsname.h>
@@ -35,6 +34,7 @@
#include <linux/freezer.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
+#include <net/ipv6.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsproto.h"
@@ -1379,8 +1379,8 @@ cifs_find_tcp_session(struct sockaddr_storage *addr)
server->addr.sockAddr.sin_addr.s_addr))
continue;
else if (addr->ss_family == AF_INET6 &&
- memcmp(&server->addr.sockAddr6.sin6_addr,
- &addr6->sin6_addr, sizeof(addr6->sin6_addr)))
+ !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr,
+ &addr6->sin6_addr))
continue;
++server->srv_count;
@@ -2180,6 +2180,33 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
"mount option supported"));
}
+static int
+is_path_accessible(int xid, struct cifsTconInfo *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path)
+{
+ int rc;
+ __u64 inode_num;
+ FILE_ALL_INFO *pfile_info;
+
+ rc = CIFSGetSrvInodeNumber(xid, tcon, full_path, &inode_num,
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (rc != -EOPNOTSUPP)
+ return rc;
+
+ pfile_info = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
+ if (pfile_info == NULL)
+ return -ENOMEM;
+
+ rc = CIFSSMBQPathInfo(xid, tcon, full_path, pfile_info,
+ 0 /* not legacy */, cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ kfree(pfile_info);
+ return rc;
+}
+
int
cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
char *mount_data, const char *devname)
@@ -2190,6 +2217,7 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
struct cifsSesInfo *pSesInfo = NULL;
struct cifsTconInfo *tcon = NULL;
struct TCP_Server_Info *srvTcp = NULL;
+ char *full_path;
xid = GetXid();
@@ -2426,6 +2454,23 @@ mount_fail_check:
cifs_sb->rsize = min(cifs_sb->rsize,
(tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
+ if (!rc && cifs_sb->prepathlen) {
+ /* build_path_to_root works only when we have a valid tcon */
+ full_path = cifs_build_path_to_root(cifs_sb);
+ if (full_path == NULL) {
+ rc = -ENOMEM;
+ goto mount_fail_check;
+ }
+ rc = is_path_accessible(xid, tcon, cifs_sb, full_path);
+ if (rc) {
+ cERROR(1, ("Path %s in not accessible: %d",
+ full_path, rc));
+ kfree(full_path);
+ goto mount_fail_check;
+ }
+ kfree(full_path);
+ }
+
/* volume_info->password is freed above when existing session found
(in which case it is not needed anymore) but when new sesion is created
the password ptr is put in the new session structure (in which case the
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c
index 964aad03c5ad..89fb72832652 100644
--- a/fs/cifs/dir.c
+++ b/fs/cifs/dir.c
@@ -3,7 +3,7 @@
*
* vfs operations that deal with dentries
*
- * Copyright (C) International Business Machines Corp., 2002,2008
+ * Copyright (C) International Business Machines Corp., 2002,2009
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
@@ -129,6 +129,78 @@ cifs_bp_rename_retry:
return full_path;
}
+static int cifs_posix_open(char *full_path, struct inode **pinode,
+ struct super_block *sb, int mode, int oflags,
+ int *poplock, __u16 *pnetfid, int xid)
+{
+ int rc;
+ __u32 oplock;
+ FILE_UNIX_BASIC_INFO *presp_data;
+ __u32 posix_flags = 0;
+ struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+
+ cFYI(1, ("posix open %s", full_path));
+
+ presp_data = kzalloc(sizeof(FILE_UNIX_BASIC_INFO), GFP_KERNEL);
+ if (presp_data == NULL)
+ return -ENOMEM;
+
+/* So far cifs posix extensions can only map the following flags.
+ There are other valid fmode oflags such as FMODE_LSEEK, FMODE_PREAD, but
+ so far we do not seem to need them, and we can treat them as local only */
+ if ((oflags & (FMODE_READ | FMODE_WRITE)) ==
+ (FMODE_READ | FMODE_WRITE))
+ posix_flags = SMB_O_RDWR;
+ else if (oflags & FMODE_READ)
+ posix_flags = SMB_O_RDONLY;
+ else if (oflags & FMODE_WRITE)
+ posix_flags = SMB_O_WRONLY;
+ if (oflags & O_CREAT)
+ posix_flags |= SMB_O_CREAT;
+ if (oflags & O_EXCL)
+ posix_flags |= SMB_O_EXCL;
+ if (oflags & O_TRUNC)
+ posix_flags |= SMB_O_TRUNC;
+ if (oflags & O_APPEND)
+ posix_flags |= SMB_O_APPEND;
+ if (oflags & O_SYNC)
+ posix_flags |= SMB_O_SYNC;
+ if (oflags & O_DIRECTORY)
+ posix_flags |= SMB_O_DIRECTORY;
+ if (oflags & O_NOFOLLOW)
+ posix_flags |= SMB_O_NOFOLLOW;
+ if (oflags & O_DIRECT)
+ posix_flags |= SMB_O_DIRECT;
+
+
+ rc = CIFSPOSIXCreate(xid, cifs_sb->tcon, posix_flags, mode,
+ pnetfid, presp_data, &oplock, full_path,
+ cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (rc)
+ goto posix_open_ret;
+
+ if (presp_data->Type == cpu_to_le32(-1))
+ goto posix_open_ret; /* open ok, caller does qpathinfo */
+
+ /* get new inode and set it up */
+ if (!pinode)
+ goto posix_open_ret; /* caller does not need info */
+
+ *pinode = cifs_new_inode(sb, &presp_data->UniqueId);
+
+ /* We do not need to close the file if new_inode fails since
+ the caller will retry qpathinfo as long as inode is null */
+ if (*pinode == NULL)
+ goto posix_open_ret;
+
+ posix_fill_in_inode(*pinode, presp_data, 1);
+
+posix_open_ret:
+ kfree(presp_data);
+ return rc;
+}
+
static void setup_cifs_dentry(struct cifsTconInfo *tcon,
struct dentry *direntry,
struct inode *newinode)
@@ -150,7 +222,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
int xid;
int create_options = CREATE_NOT_DIR;
int oplock = 0;
- /* BB below access is too much for the mknod to request */
+ int oflags;
+ /*
+ * BB below access is probably too much for mknod to request
+ * but we have to do query and setpathinfo so requesting
+ * less could fail (unless we want to request getatr and setatr
+ * permissions (only). At least for POSIX we do not have to
+ * request so much.
+ */
int desiredAccess = GENERIC_READ | GENERIC_WRITE;
__u16 fileHandle;
struct cifs_sb_info *cifs_sb;
@@ -174,13 +253,43 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
}
mode &= ~current->fs->umask;
+ if (oplockEnabled)
+ oplock = REQ_OPLOCK;
- if (nd && (nd->flags & LOOKUP_OPEN)) {
- int oflags = nd->intent.open.flags;
+ if (nd && (nd->flags & LOOKUP_OPEN))
+ oflags = nd->intent.open.flags;
+ else
+ oflags = FMODE_READ;
+
+ if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
+ (CIFS_UNIX_POSIX_PATH_OPS_CAP &
+ le64_to_cpu(tcon->fsUnixInfo.Capability))) {
+ rc = cifs_posix_open(full_path, &newinode, inode->i_sb,
+ mode, oflags, &oplock, &fileHandle, xid);
+ /* EIO could indicate that (posix open) operation is not
+ supported, despite what server claimed in capability
+ negotation. EREMOTE indicates DFS junction, which is not
+ handled in posix open */
+
+ if ((rc == 0) && (newinode == NULL))
+ goto cifs_create_get_file_info; /* query inode info */
+ else if (rc == 0) /* success, no need to query */
+ goto cifs_create_set_dentry;
+ else if ((rc != -EIO) && (rc != -EREMOTE) &&
+ (rc != -EOPNOTSUPP)) /* path not found or net err */
+ goto cifs_create_out;
+ /* else fallthrough to retry, using older open call, this is
+ case where server does not support this SMB level, and
+ falsely claims capability (also get here for DFS case
+ which should be rare for path not covered on files) */
+ }
+ if (nd && (nd->flags & LOOKUP_OPEN)) {
+ /* if the file is going to stay open, then we
+ need to set the desired access properly */
desiredAccess = 0;
if (oflags & FMODE_READ)
- desiredAccess |= GENERIC_READ;
+ desiredAccess |= GENERIC_READ; /* is this too little? */
if (oflags & FMODE_WRITE) {
desiredAccess |= GENERIC_WRITE;
if (!(oflags & FMODE_READ))
@@ -199,8 +308,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
/* BB add processing to set equivalent of mode - e.g. via CreateX with
ACLs */
- if (oplockEnabled)
- oplock = REQ_OPLOCK;
buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if (buf == NULL) {
@@ -233,116 +340,112 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
}
if (rc) {
cFYI(1, ("cifs_create returned 0x%x", rc));
- } else {
- /* If Open reported that we actually created a file
- then we now have to set the mode if possible */
- if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
- struct cifs_unix_set_info_args args = {
+ goto cifs_create_out;
+ }
+
+ /* If Open reported that we actually created a file
+ then we now have to set the mode if possible */
+ if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
+ struct cifs_unix_set_info_args args = {
.mode = mode,
.ctime = NO_CHANGE_64,
.atime = NO_CHANGE_64,
.mtime = NO_CHANGE_64,
.device = 0,
- };
+ };
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
- args.uid = (__u64) current_fsuid();
- if (inode->i_mode & S_ISGID)
- args.gid = (__u64) inode->i_gid;
- else
- args.gid = (__u64) current_fsgid();
- } else {
- args.uid = NO_CHANGE_64;
- args.gid = NO_CHANGE_64;
- }
- CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
+ args.uid = (__u64) current_fsuid();
+ if (inode->i_mode & S_ISGID)
+ args.gid = (__u64) inode->i_gid;
+ else
+ args.gid = (__u64) current_fsgid();
} else {
- /* BB implement mode setting via Windows security
- descriptors e.g. */
- /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
-
- /* Could set r/o dos attribute if mode & 0222 == 0 */
+ args.uid = NO_CHANGE_64;
+ args.gid = NO_CHANGE_64;
}
+ CIFSSMBUnixSetInfo(xid, tcon, full_path, &args,
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+ } else {
+ /* BB implement mode setting via Windows security
+ descriptors e.g. */
+ /* CIFSSMBWinSetPerms(xid,tcon,path,mode,-1,-1,nls);*/
- /* server might mask mode so we have to query for it */
- if (tcon->unix_ext)
- rc = cifs_get_inode_info_unix(&newinode, full_path,
- inode->i_sb, xid);
- else {
- rc = cifs_get_inode_info(&newinode, full_path,
- buf, inode->i_sb, xid,
- &fileHandle);
- if (newinode) {
- if (cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_DYNPERM)
- newinode->i_mode = mode;
- if ((oplock & CIFS_CREATE_ACTION) &&
- (cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_SET_UID)) {
- newinode->i_uid = current_fsuid();
- if (inode->i_mode & S_ISGID)
- newinode->i_gid =
- inode->i_gid;
- else
- newinode->i_gid =
- current_fsgid();
- }
+ /* Could set r/o dos attribute if mode & 0222 == 0 */
+ }
+
+cifs_create_get_file_info:
+ /* server might mask mode so we have to query for it */
+ if (tcon->unix_ext)
+ rc = cifs_get_inode_info_unix(&newinode, full_path,
+ inode->i_sb, xid);
+ else {
+ rc = cifs_get_inode_info(&newinode, full_path, buf,
+ inode->i_sb, xid, &fileHandle);
+ if (newinode) {
+ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
+ newinode->i_mode = mode;
+ if ((oplock & CIFS_CREATE_ACTION) &&
+ (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
+ newinode->i_uid = current_fsuid();
+ if (inode->i_mode & S_ISGID)
+ newinode->i_gid = inode->i_gid;
+ else
+ newinode->i_gid = current_fsgid();
}
}
+ }
- if (rc != 0) {
- cFYI(1, ("Create worked, get_inode_info failed rc = %d",
- rc));
- } else
- setup_cifs_dentry(tcon, direntry, newinode);
-
- if ((nd == NULL /* nfsd case - nfs srv does not set nd */) ||
- (!(nd->flags & LOOKUP_OPEN))) {
- /* mknod case - do not leave file open */
- CIFSSMBClose(xid, tcon, fileHandle);
- } else if (newinode) {
- struct cifsFileInfo *pCifsFile =
- kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
-
- if (pCifsFile == NULL)
- goto cifs_create_out;
- pCifsFile->netfid = fileHandle;
- pCifsFile->pid = current->tgid;
- pCifsFile->pInode = newinode;
- pCifsFile->invalidHandle = false;
- pCifsFile->closePend = false;
- init_MUTEX(&pCifsFile->fh_sem);
- mutex_init(&pCifsFile->lock_mutex);
- INIT_LIST_HEAD(&pCifsFile->llist);
- atomic_set(&pCifsFile->wrtPending, 0);
-
- /* set the following in open now
+cifs_create_set_dentry:
+ if (rc == 0)
+ setup_cifs_dentry(tcon, direntry, newinode);
+ else
+ cFYI(1, ("Create worked, get_inode_info failed rc = %d", rc));
+
+ /* nfsd case - nfs srv does not set nd */
+ if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
+ /* mknod case - do not leave file open */
+ CIFSSMBClose(xid, tcon, fileHandle);
+ } else if (newinode) {
+ struct cifsFileInfo *pCifsFile =
+ kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
+
+ if (pCifsFile == NULL)
+ goto cifs_create_out;
+ pCifsFile->netfid = fileHandle;
+ pCifsFile->pid = current->tgid;
+ pCifsFile->pInode = newinode;
+ pCifsFile->invalidHandle = false;
+ pCifsFile->closePend = false;
+ init_MUTEX(&pCifsFile->fh_sem);
+ mutex_init(&pCifsFile->lock_mutex);
+ INIT_LIST_HEAD(&pCifsFile->llist);
+ atomic_set(&pCifsFile->wrtPending, 0);
+
+ /* set the following in open now
pCifsFile->pfile = file; */
- write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist, &tcon->openFileList);
- pCifsInode = CIFS_I(newinode);
- if (pCifsInode) {
- /* if readable file instance put first in list*/
- if (write_only) {
- list_add_tail(&pCifsFile->flist,
- &pCifsInode->openFileList);
- } else {
- list_add(&pCifsFile->flist,
- &pCifsInode->openFileList);
- }
- if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
- pCifsInode->clientCanCacheAll = true;
- pCifsInode->clientCanCacheRead = true;
- cFYI(1, ("Exclusive Oplock inode %p",
- newinode));
- } else if ((oplock & 0xF) == OPLOCK_READ)
- pCifsInode->clientCanCacheRead = true;
+ write_lock(&GlobalSMBSeslock);
+ list_add(&pCifsFile->tlist, &tcon->openFileList);
+ pCifsInode = CIFS_I(newinode);
+ if (pCifsInode) {
+ /* if readable file instance put first in list*/
+ if (write_only) {
+ list_add_tail(&pCifsFile->flist,
+ &pCifsInode->openFileList);
+ } else {
+ list_add(&pCifsFile->flist,
+ &pCifsInode->openFileList);
}
- write_unlock(&GlobalSMBSeslock);
+ if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
+ pCifsInode->clientCanCacheAll = true;
+ pCifsInode->clientCanCacheRead = true;
+ cFYI(1, ("Exclusive Oplock inode %p",
+ newinode));
+ } else if ((oplock & 0xF) == OPLOCK_READ)
+ pCifsInode->clientCanCacheRead = true;
}
+ write_unlock(&GlobalSMBSeslock);
}
cifs_create_out:
kfree(buf);
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index bcf7b5184664..4690a360c855 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -199,6 +199,49 @@ static void fill_fake_finddataunix(FILE_UNIX_BASIC_INFO *pfnd_dat,
pfnd_dat->Gid = cpu_to_le64(pinode->i_gid);
}
+/**
+ * cifs_new inode - create new inode, initialize, and hash it
+ * @sb - pointer to superblock
+ * @inum - if valid pointer and serverino is enabled, replace i_ino with val
+ *
+ * Create a new inode, initialize it for CIFS and hash it. Returns the new
+ * inode or NULL if one couldn't be allocated.
+ *
+ * If the share isn't mounted with "serverino" or inum is a NULL pointer then
+ * we'll just use the inode number assigned by new_inode(). Note that this can
+ * mean i_ino collisions since the i_ino assigned by new_inode is not
+ * guaranteed to be unique.
+ */
+struct inode *
+cifs_new_inode(struct super_block *sb, __u64 *inum)
+{
+ struct inode *inode;
+
+ inode = new_inode(sb);
+ if (inode == NULL)
+ return NULL;
+
+ /*
+ * BB: Is i_ino == 0 legal? Here, we assume that it is. If it isn't we
+ * stop passing inum as ptr. Are there sanity checks we can use to
+ * ensure that the server is really filling in that field? Also,
+ * if serverino is disabled, perhaps we should be using iunique()?
+ */
+ if (inum && (CIFS_SB(sb)->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM))
+ inode->i_ino = (unsigned long) *inum;
+
+ /*
+ * must set this here instead of cifs_alloc_inode since VFS will
+ * clobber i_flags
+ */
+ if (sb->s_flags & MS_NOATIME)
+ inode->i_flags |= S_NOATIME | S_NOCMTIME;
+
+ insert_inode_hash(inode);
+
+ return inode;
+}
+
int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *full_path, struct super_block *sb, int xid)
{
@@ -233,22 +276,11 @@ int cifs_get_inode_info_unix(struct inode **pinode,
/* get new inode */
if (*pinode == NULL) {
- *pinode = new_inode(sb);
+ *pinode = cifs_new_inode(sb, &find_data.UniqueId);
if (*pinode == NULL) {
rc = -ENOMEM;
goto cgiiu_exit;
}
- /* Is an i_ino of zero legal? */
- /* note ino incremented to unique num in new_inode */
- /* Are there sanity checks we can use to ensure that
- the server is really filling in that field? */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
- (*pinode)->i_ino = (unsigned long)find_data.UniqueId;
-
- if (sb->s_flags & MS_NOATIME)
- (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
-
- insert_inode_hash(*pinode);
}
inode = *pinode;
@@ -465,11 +497,9 @@ int cifs_get_inode_info(struct inode **pinode,
/* get new inode */
if (*pinode == NULL) {
- *pinode = new_inode(sb);
- if (*pinode == NULL) {
- rc = -ENOMEM;
- goto cgii_exit;
- }
+ __u64 inode_num;
+ __u64 *pinum = &inode_num;
+
/* Is an i_ino of zero legal? Can we use that to check
if the server supports returning inode numbers? Are
there other sanity checks we can use to ensure that
@@ -486,22 +516,26 @@ int cifs_get_inode_info(struct inode **pinode,
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
int rc1 = 0;
- __u64 inode_num;
rc1 = CIFSGetSrvInodeNumber(xid, pTcon,
- full_path, &inode_num,
+ full_path, pinum,
cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc1) {
cFYI(1, ("GetSrvInodeNum rc %d", rc1));
+ pinum = NULL;
/* BB EOPNOSUPP disable SERVER_INUM? */
- } else /* do we need cast or hash to ino? */
- (*pinode)->i_ino = inode_num;
- } /* else ino incremented to unique num in new_inode*/
- if (sb->s_flags & MS_NOATIME)
- (*pinode)->i_flags |= S_NOATIME | S_NOCMTIME;
- insert_inode_hash(*pinode);
+ }
+ } else {
+ pinum = NULL;
+ }
+
+ *pinode = cifs_new_inode(sb, pinum);
+ if (*pinode == NULL) {
+ rc = -ENOMEM;
+ goto cgii_exit;
+ }
}
inode = *pinode;
cifsInfo = CIFS_I(inode);
@@ -621,7 +655,7 @@ static const struct inode_operations cifs_ipc_inode_ops = {
.lookup = cifs_lookup,
};
-static char *build_path_to_root(struct cifs_sb_info *cifs_sb)
+char *cifs_build_path_to_root(struct cifs_sb_info *cifs_sb)
{
int pplen = cifs_sb->prepathlen;
int dfsplen;
@@ -678,7 +712,7 @@ struct inode *cifs_iget(struct super_block *sb, unsigned long ino)
return inode;
cifs_sb = CIFS_SB(inode->i_sb);
- full_path = build_path_to_root(cifs_sb);
+ full_path = cifs_build_path_to_root(cifs_sb);
if (full_path == NULL)
return ERR_PTR(-ENOMEM);
@@ -1017,7 +1051,7 @@ out_reval:
return rc;
}
-static void posix_fill_in_inode(struct inode *tmp_inode,
+void posix_fill_in_inode(struct inode *tmp_inode,
FILE_UNIX_BASIC_INFO *pData, int isNewInode)
{
struct cifsInodeInfo *cifsInfo = CIFS_I(tmp_inode);
@@ -1114,24 +1148,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
else
direntry->d_op = &cifs_dentry_ops;
- newinode = new_inode(inode->i_sb);
+ newinode = cifs_new_inode(inode->i_sb,
+ &pInfo->UniqueId);
if (newinode == NULL) {
kfree(pInfo);
goto mkdir_get_info;
}
- /* Is an i_ino of zero legal? */
- /* Are there sanity checks we can use to ensure that
- the server is really filling in that field? */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) {
- newinode->i_ino =
- (unsigned long)pInfo->UniqueId;
- } /* note ino incremented to unique num in new_inode */
- if (inode->i_sb->s_flags & MS_NOATIME)
- newinode->i_flags |= S_NOATIME | S_NOCMTIME;
newinode->i_nlink = 2;
-
- insert_inode_hash(newinode);
d_instantiate(direntry, newinode);
/* we already checked in POSIXCreate whether
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 9f51f9bf0292..c2c01ff4c32c 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -56,35 +56,34 @@ static inline void dump_cifs_file_struct(struct file *file, char *label)
}
#endif /* DEBUG2 */
-/* Returns one if new inode created (which therefore needs to be hashed) */
+/* Returns 1 if new inode created, 2 if both dentry and inode were */
/* Might check in the future if inode number changed so we can rehash inode */
-static int construct_dentry(struct qstr *qstring, struct file *file,
- struct inode **ptmp_inode, struct dentry **pnew_dentry)
+static int
+construct_dentry(struct qstr *qstring, struct file *file,
+ struct inode **ptmp_inode, struct dentry **pnew_dentry,
+ __u64 *inum)
{
- struct dentry *tmp_dentry;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
+ struct dentry *tmp_dentry = NULL;
+ struct super_block *sb = file->f_path.dentry->d_sb;
int rc = 0;
cFYI(1, ("For %s", qstring->name));
- cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
- pTcon = cifs_sb->tcon;
qstring->hash = full_name_hash(qstring->name, qstring->len);
tmp_dentry = d_lookup(file->f_path.dentry, qstring);
if (tmp_dentry) {
+ /* BB: overwrite old name? i.e. tmp_dentry->d_name and
+ * tmp_dentry->d_name.len??
+ */
cFYI(0, ("existing dentry with inode 0x%p",
tmp_dentry->d_inode));
*ptmp_inode = tmp_dentry->d_inode;
-/* BB overwrite old name? i.e. tmp_dentry->d_name and tmp_dentry->d_name.len??*/
if (*ptmp_inode == NULL) {
- *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
+ *ptmp_inode = cifs_new_inode(sb, inum);
if (*ptmp_inode == NULL)
return rc;
rc = 1;
}
- if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
- (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
} else {
tmp_dentry = d_alloc(file->f_path.dentry, qstring);
if (tmp_dentry == NULL) {
@@ -93,15 +92,14 @@ static int construct_dentry(struct qstr *qstring, struct file *file,
return rc;
}
- *ptmp_inode = new_inode(file->f_path.dentry->d_sb);
- if (pTcon->nocase)
+ if (CIFS_SB(sb)->tcon->nocase)
tmp_dentry->d_op = &cifs_ci_dentry_ops;
else
tmp_dentry->d_op = &cifs_dentry_ops;
+
+ *ptmp_inode = cifs_new_inode(sb, inum);
if (*ptmp_inode == NULL)
return rc;
- if (file->f_path.dentry->d_sb->s_flags & MS_NOATIME)
- (*ptmp_inode)->i_flags |= S_NOATIME | S_NOCMTIME;
rc = 2;
}
@@ -822,7 +820,7 @@ static int find_cifs_entry(const int xid, struct cifsTconInfo *pTcon,
/* inode num, inode type and filename returned */
static int cifs_get_name_from_search_buf(struct qstr *pqst,
char *current_entry, __u16 level, unsigned int unicode,
- struct cifs_sb_info *cifs_sb, int max_len, ino_t *pinum)
+ struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum)
{
int rc = 0;
unsigned int len = 0;
@@ -842,9 +840,7 @@ static int cifs_get_name_from_search_buf(struct qstr *pqst,
len = strnlen(filename, PATH_MAX);
}
- /* BB fixme - hash low and high 32 bits if not 64 bit arch BB */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)
- *pinum = pFindData->UniqueId;
+ *pinum = pFindData->UniqueId;
} else if (level == SMB_FIND_FILE_DIRECTORY_INFO) {
FILE_DIRECTORY_INFO *pFindData =
(FILE_DIRECTORY_INFO *)current_entry;
@@ -907,7 +903,7 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
struct qstr qstring;
struct cifsFileInfo *pCifsF;
unsigned int obj_type;
- ino_t inum;
+ __u64 inum;
struct cifs_sb_info *cifs_sb;
struct inode *tmp_inode;
struct dentry *tmp_dentry;
@@ -940,20 +936,18 @@ static int cifs_filldir(char *pfindEntry, struct file *file,
if (rc)
return rc;
- rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry);
+ /* only these two infolevels return valid inode numbers */
+ if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX ||
+ pCifsF->srch_inf.info_level == SMB_FIND_FILE_ID_FULL_DIR_INFO)
+ rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
+ &inum);
+ else
+ rc = construct_dentry(&qstring, file, &tmp_inode, &tmp_dentry,
+ NULL);
+
if ((tmp_inode == NULL) || (tmp_dentry == NULL))
return -ENOMEM;
- if (rc) {
- /* inode created, we need to hash it with right inode number */
- if (inum != 0) {
- /* BB fixme - hash the 2 32 quantities bits together if
- * necessary BB */
- tmp_inode->i_ino = inum;
- }
- insert_inode_hash(tmp_inode);
- }
-
/* we pass in rc below, indicating whether it is a new inode,
so we can figure out whether to invalidate the inode cached
data if the file has changed */
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c
index 5f22de7b79a9..5c68b4282be9 100644
--- a/fs/cifs/sess.c
+++ b/fs/cifs/sess.c
@@ -34,15 +34,99 @@
extern void SMBNTencrypt(unsigned char *passwd, unsigned char *c8,
unsigned char *p24);
+/* Checks if this is the first smb session to be reconnected after
+ the socket has been reestablished (so we know whether to use vc 0).
+ Called while holding the cifs_tcp_ses_lock, so do not block */
+static bool is_first_ses_reconnect(struct cifsSesInfo *ses)
+{
+ struct list_head *tmp;
+ struct cifsSesInfo *tmp_ses;
+
+ list_for_each(tmp, &ses->server->smb_ses_list) {
+ tmp_ses = list_entry(tmp, struct cifsSesInfo,
+ smb_ses_list);
+ if (tmp_ses->need_reconnect == false)
+ return false;
+ }
+ /* could not find a session that was already connected,
+ this must be the first one we are reconnecting */
+ return true;
+}
+
+/*
+ * vc number 0 is treated specially by some servers, and should be the
+ * first one we request. After that we can use vcnumbers up to maxvcs,
+ * one for each smb session (some Windows versions set maxvcs incorrectly
+ * so maxvc=1 can be ignored). If we have too many vcs, we can reuse
+ * any vc but zero (some servers reset the connection on vcnum zero)
+ *
+ */
+static __le16 get_next_vcnum(struct cifsSesInfo *ses)
+{
+ __u16 vcnum = 0;
+ struct list_head *tmp;
+ struct cifsSesInfo *tmp_ses;
+ __u16 max_vcs = ses->server->max_vcs;
+ __u16 i;
+ int free_vc_found = 0;
+
+ /* Quoting the MS-SMB specification: "Windows-based SMB servers set this
+ field to one but do not enforce this limit, which allows an SMB client
+ to establish more virtual circuits than allowed by this value ... but
+ other server implementations can enforce this limit." */
+ if (max_vcs < 2)
+ max_vcs = 0xFFFF;
+
+ write_lock(&cifs_tcp_ses_lock);
+ if ((ses->need_reconnect) && is_first_ses_reconnect(ses))
+ goto get_vc_num_exit; /* vcnum will be zero */
+ for (i = ses->server->srv_count - 1; i < max_vcs; i++) {
+ if (i == 0) /* this is the only connection, use vc 0 */
+ break;
+
+ free_vc_found = 1;
+
+ list_for_each(tmp, &ses->server->smb_ses_list) {
+ tmp_ses = list_entry(tmp, struct cifsSesInfo,
+ smb_ses_list);
+ if (tmp_ses->vcnum == i) {
+ free_vc_found = 0;
+ break; /* found duplicate, try next vcnum */
+ }
+ }
+ if (free_vc_found)
+ break; /* we found a vcnumber that will work - use it */
+ }
+
+ if (i == 0)
+ vcnum = 0; /* for most common case, ie if one smb session, use
+ vc zero. Also for case when no free vcnum, zero
+ is safest to send (some clients only send zero) */
+ else if (free_vc_found == 0)
+ vcnum = 1; /* we can not reuse vc=0 safely, since some servers
+ reset all uids on that, but 1 is ok. */
+ else
+ vcnum = i;
+ ses->vcnum = vcnum;
+get_vc_num_exit:
+ write_unlock(&cifs_tcp_ses_lock);
+
+ return le16_to_cpu(vcnum);
+}
+
static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
{
__u32 capabilities = 0;
/* init fields common to all four types of SessSetup */
- /* note that header is initialized to zero in header_assemble */
+ /* Note that offsets for first seven fields in req struct are same */
+ /* in CIFS Specs so does not matter which of 3 forms of struct */
+ /* that we use in next few lines */
+ /* Note that header is initialized to zero in header_assemble */
pSMB->req.AndXCommand = 0xFF;
pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
+ pSMB->req.VcNumber = get_next_vcnum(ses);
/* Now no need to set SMBFLG_CASELESS or obsolete CANONICAL PATH */
@@ -71,7 +155,6 @@ static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
if (ses->capabilities & CAP_UNIX)
capabilities |= CAP_UNIX;
- /* BB check whether to init vcnum BB */
return capabilities;
}
@@ -228,7 +311,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
kfree(ses->serverOS);
/* UTF-8 string will not grow more than four times as big as UCS-16 */
- ses->serverOS = kzalloc(4 * len, GFP_KERNEL);
+ ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
if (ses->serverOS != NULL)
cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
data += 2 * (len + 1);
@@ -241,7 +324,7 @@ static int decode_unicode_ssetup(char **pbcc_area, int bleft,
return rc;
kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(4 * len, GFP_KERNEL); /* BB this is wrong length FIXME BB */
+ ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
if (ses->serverNOS != NULL) {
cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
nls_cp);
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c
index 9c6d815dd191..39bd4d38e889 100644
--- a/fs/compat_ioctl.c
+++ b/fs/compat_ioctl.c
@@ -1938,6 +1938,8 @@ ULONG_IOCTL(SET_BITMAP_FILE)
/* Big K */
COMPATIBLE_IOCTL(PIO_FONT)
COMPATIBLE_IOCTL(GIO_FONT)
+COMPATIBLE_IOCTL(PIO_CMAP)
+COMPATIBLE_IOCTL(GIO_CMAP)
ULONG_IOCTL(KDSIGACCEPT)
COMPATIBLE_IOCTL(KDGETKEYCODE)
COMPATIBLE_IOCTL(KDSETKEYCODE)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index aafc9eba1c25..b0c87dce66a3 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -868,7 +868,7 @@ static inline unsigned ext4_rec_len_from_disk(__le16 dlen)
{
unsigned len = le16_to_cpu(dlen);
- if (len == EXT4_MAX_REC_LEN)
+ if (len == EXT4_MAX_REC_LEN || len == 0)
return 1 << 16;
return len;
}
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 03ba20be1329..cbd2ca99d113 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -47,8 +47,10 @@
static inline int ext4_begin_ordered_truncate(struct inode *inode,
loff_t new_size)
{
- return jbd2_journal_begin_ordered_truncate(&EXT4_I(inode)->jinode,
- new_size);
+ return jbd2_journal_begin_ordered_truncate(
+ EXT4_SB(inode->i_sb)->s_journal,
+ &EXT4_I(inode)->jinode,
+ new_size);
}
static void ext4_invalidatepage(struct page *page, unsigned long offset);
@@ -2437,6 +2439,7 @@ static int ext4_da_writepages(struct address_space *mapping,
int no_nrwrite_index_update;
int pages_written = 0;
long pages_skipped;
+ int range_cyclic, cycled = 1, io_done = 0;
int needed_blocks, ret = 0, nr_to_writebump = 0;
struct ext4_sb_info *sbi = EXT4_SB(mapping->host->i_sb);
@@ -2488,9 +2491,15 @@ static int ext4_da_writepages(struct address_space *mapping,
if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX)
range_whole = 1;
- if (wbc->range_cyclic)
+ range_cyclic = wbc->range_cyclic;
+ if (wbc->range_cyclic) {
index = mapping->writeback_index;
- else
+ if (index)
+ cycled = 0;
+ wbc->range_start = index << PAGE_CACHE_SHIFT;
+ wbc->range_end = LLONG_MAX;
+ wbc->range_cyclic = 0;
+ } else
index = wbc->range_start >> PAGE_CACHE_SHIFT;
mpd.wbc = wbc;
@@ -2504,6 +2513,7 @@ static int ext4_da_writepages(struct address_space *mapping,
wbc->no_nrwrite_index_update = 1;
pages_skipped = wbc->pages_skipped;
+retry:
while (!ret && wbc->nr_to_write > 0) {
/*
@@ -2546,6 +2556,7 @@ static int ext4_da_writepages(struct address_space *mapping,
pages_written += mpd.pages_written;
wbc->pages_skipped = pages_skipped;
ret = 0;
+ io_done = 1;
} else if (wbc->nr_to_write)
/*
* There is no more writeout needed
@@ -2554,6 +2565,13 @@ static int ext4_da_writepages(struct address_space *mapping,
*/
break;
}
+ if (!io_done && !cycled) {
+ cycled = 1;
+ index = 0;
+ wbc->range_start = index << PAGE_CACHE_SHIFT;
+ wbc->range_end = mapping->writeback_index - 1;
+ goto retry;
+ }
if (pages_skipped != wbc->pages_skipped)
printk(KERN_EMERG "This should not happen leaving %s "
"with nr_to_write = %ld ret = %d\n",
@@ -2561,6 +2579,7 @@ static int ext4_da_writepages(struct address_space *mapping,
/* Update index */
index += pages_written;
+ wbc->range_cyclic = range_cyclic;
if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
/*
* set the writeback_index so that range_cyclic
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index deba54f6cbed..4415beeb0b62 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -3693,6 +3693,8 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
pa->pa_free = pa->pa_len;
atomic_set(&pa->pa_count, 1);
spin_lock_init(&pa->pa_lock);
+ INIT_LIST_HEAD(&pa->pa_inode_list);
+ INIT_LIST_HEAD(&pa->pa_group_list);
pa->pa_deleted = 0;
pa->pa_linear = 0;
@@ -3755,6 +3757,7 @@ ext4_mb_new_group_pa(struct ext4_allocation_context *ac)
atomic_set(&pa->pa_count, 1);
spin_lock_init(&pa->pa_lock);
INIT_LIST_HEAD(&pa->pa_inode_list);
+ INIT_LIST_HEAD(&pa->pa_group_list);
pa->pa_deleted = 0;
pa->pa_linear = 1;
@@ -4476,23 +4479,26 @@ static int ext4_mb_release_context(struct ext4_allocation_context *ac)
pa->pa_free -= ac->ac_b_ex.fe_len;
pa->pa_len -= ac->ac_b_ex.fe_len;
spin_unlock(&pa->pa_lock);
- /*
- * We want to add the pa to the right bucket.
- * Remove it from the list and while adding
- * make sure the list to which we are adding
- * doesn't grow big.
- */
- if (likely(pa->pa_free)) {
- spin_lock(pa->pa_obj_lock);
- list_del_rcu(&pa->pa_inode_list);
- spin_unlock(pa->pa_obj_lock);
- ext4_mb_add_n_trim(ac);
- }
}
- ext4_mb_put_pa(ac, ac->ac_sb, pa);
}
if (ac->alloc_semp)
up_read(ac->alloc_semp);
+ if (pa) {
+ /*
+ * We want to add the pa to the right bucket.
+ * Remove it from the list and while adding
+ * make sure the list to which we are adding
+ * doesn't grow big. We need to release
+ * alloc_semp before calling ext4_mb_add_n_trim()
+ */
+ if (pa->pa_linear && likely(pa->pa_free)) {
+ spin_lock(pa->pa_obj_lock);
+ list_del_rcu(&pa->pa_inode_list);
+ spin_unlock(pa->pa_obj_lock);
+ ext4_mb_add_n_trim(ac);
+ }
+ ext4_mb_put_pa(ac, ac->ac_sb, pa);
+ }
if (ac->ac_bitmap_page)
page_cache_release(ac->ac_bitmap_page);
if (ac->ac_buddy_page)
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c
index 734abca25e35..fe64d9f79852 100644
--- a/fs/ext4/migrate.c
+++ b/fs/ext4/migrate.c
@@ -481,7 +481,7 @@ int ext4_ext_migrate(struct inode *inode)
+ 1);
if (IS_ERR(handle)) {
retval = PTR_ERR(handle);
- goto err_out;
+ return retval;
}
tmp_inode = ext4_new_inode(handle,
inode->i_sb->s_root->d_inode,
@@ -489,8 +489,7 @@ int ext4_ext_migrate(struct inode *inode)
if (IS_ERR(tmp_inode)) {
retval = -ENOMEM;
ext4_journal_stop(handle);
- tmp_inode = NULL;
- goto err_out;
+ return retval;
}
i_size_write(tmp_inode, i_size_read(inode));
/*
@@ -618,8 +617,7 @@ err_out:
ext4_journal_stop(handle);
- if (tmp_inode)
- iput(tmp_inode);
+ iput(tmp_inode);
return retval;
}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index e5f06a5f045e..a5732c58f676 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3046,14 +3046,17 @@ static void ext4_write_super(struct super_block *sb)
static int ext4_sync_fs(struct super_block *sb, int wait)
{
int ret = 0;
+ tid_t target;
trace_mark(ext4_sync_fs, "dev %s wait %d", sb->s_id, wait);
sb->s_dirt = 0;
if (EXT4_SB(sb)->s_journal) {
- if (wait)
- ret = ext4_force_commit(sb);
- else
- jbd2_journal_start_commit(EXT4_SB(sb)->s_journal, NULL);
+ if (jbd2_journal_start_commit(EXT4_SB(sb)->s_journal,
+ &target)) {
+ if (wait)
+ jbd2_log_wait_commit(EXT4_SB(sb)->s_journal,
+ target);
+ }
} else {
ext4_commit_super(sb, EXT4_SB(sb)->s_es, wait);
}
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index eb343008eded..58144102bf25 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -450,7 +450,7 @@ int __jbd2_log_space_left(journal_t *journal)
}
/*
- * Called under j_state_lock. Returns true if a transaction was started.
+ * Called under j_state_lock. Returns true if a transaction commit was started.
*/
int __jbd2_log_start_commit(journal_t *journal, tid_t target)
{
@@ -518,7 +518,8 @@ int jbd2_journal_force_commit_nested(journal_t *journal)
/*
* Start a commit of the current running transaction (if any). Returns true
- * if a transaction was started, and fills its tid in at *ptid
+ * if a transaction is going to be committed (or is currently already
+ * committing), and fills its tid in at *ptid
*/
int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid)
{
@@ -528,15 +529,19 @@ int jbd2_journal_start_commit(journal_t *journal, tid_t *ptid)
if (journal->j_running_transaction) {
tid_t tid = journal->j_running_transaction->t_tid;
- ret = __jbd2_log_start_commit(journal, tid);
- if (ret && ptid)
+ __jbd2_log_start_commit(journal, tid);
+ /* There's a running transaction and we've just made sure
+ * it's commit has been scheduled. */
+ if (ptid)
*ptid = tid;
- } else if (journal->j_committing_transaction && ptid) {
+ ret = 1;
+ } else if (journal->j_committing_transaction) {
/*
* If ext3_write_super() recently started a commit, then we
* have to wait for completion of that transaction
*/
- *ptid = journal->j_committing_transaction->t_tid;
+ if (ptid)
+ *ptid = journal->j_committing_transaction->t_tid;
ret = 1;
}
spin_unlock(&journal->j_state_lock);
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c
index 46b4e347ed7d..28ce21d8598e 100644
--- a/fs/jbd2/transaction.c
+++ b/fs/jbd2/transaction.c
@@ -2129,26 +2129,46 @@ done:
}
/*
- * This function must be called when inode is journaled in ordered mode
- * before truncation happens. It starts writeout of truncated part in
- * case it is in the committing transaction so that we stand to ordered
- * mode consistency guarantees.
+ * File truncate and transaction commit interact with each other in a
+ * non-trivial way. If a transaction writing data block A is
+ * committing, we cannot discard the data by truncate until we have
+ * written them. Otherwise if we crashed after the transaction with
+ * write has committed but before the transaction with truncate has
+ * committed, we could see stale data in block A. This function is a
+ * helper to solve this problem. It starts writeout of the truncated
+ * part in case it is in the committing transaction.
+ *
+ * Filesystem code must call this function when inode is journaled in
+ * ordered mode before truncation happens and after the inode has been
+ * placed on orphan list with the new inode size. The second condition
+ * avoids the race that someone writes new data and we start
+ * committing the transaction after this function has been called but
+ * before a transaction for truncate is started (and furthermore it
+ * allows us to optimize the case where the addition to orphan list
+ * happens in the same transaction as write --- we don't have to write
+ * any data in such case).
*/
-int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode,
+int jbd2_journal_begin_ordered_truncate(journal_t *journal,
+ struct jbd2_inode *jinode,
loff_t new_size)
{
- journal_t *journal;
- transaction_t *commit_trans;
+ transaction_t *inode_trans, *commit_trans;
int ret = 0;
- if (!inode->i_transaction && !inode->i_next_transaction)
+ /* This is a quick check to avoid locking if not necessary */
+ if (!jinode->i_transaction)
goto out;
- journal = inode->i_transaction->t_journal;
+ /* Locks are here just to force reading of recent values, it is
+ * enough that the transaction was not committing before we started
+ * a transaction adding the inode to orphan list */
spin_lock(&journal->j_state_lock);
commit_trans = journal->j_committing_transaction;
spin_unlock(&journal->j_state_lock);
- if (inode->i_transaction == commit_trans) {
- ret = filemap_fdatawrite_range(inode->i_vfs_inode->i_mapping,
+ spin_lock(&journal->j_list_lock);
+ inode_trans = jinode->i_transaction;
+ spin_unlock(&journal->j_list_lock);
+ if (inode_trans == commit_trans) {
+ ret = filemap_fdatawrite_range(jinode->i_vfs_inode->i_mapping,
new_size, LLONG_MAX);
if (ret)
jbd2_journal_abort(journal, ret);
diff --git a/fs/namespace.c b/fs/namespace.c
index 228d8c4bfd18..06f8e63f6cb1 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -614,9 +614,11 @@ static inline void __mntput(struct vfsmount *mnt)
*/
for_each_possible_cpu(cpu) {
struct mnt_writer *cpu_writer = &per_cpu(mnt_writers, cpu);
- if (cpu_writer->mnt != mnt)
- continue;
spin_lock(&cpu_writer->lock);
+ if (cpu_writer->mnt != mnt) {
+ spin_unlock(&cpu_writer->lock);
+ continue;
+ }
atomic_add(cpu_writer->count, &mnt->__mnt_writers);
cpu_writer->count = 0;
/*
diff --git a/fs/notify/inotify/inotify.c b/fs/notify/inotify/inotify.c
index dae3f28f30d4..331f2e88e284 100644
--- a/fs/notify/inotify/inotify.c
+++ b/fs/notify/inotify/inotify.c
@@ -156,7 +156,7 @@ static int inotify_handle_get_wd(struct inotify_handle *ih,
int ret;
do {
- if (unlikely(!idr_pre_get(&ih->idr, GFP_KERNEL)))
+ if (unlikely(!idr_pre_get(&ih->idr, GFP_NOFS)))
return -ENOSPC;
ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd);
} while (ret == -EAGAIN);
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index 3c3532e1307c..172850a9a12a 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -513,8 +513,10 @@ static inline int ocfs2_jbd2_file_inode(handle_t *handle, struct inode *inode)
static inline int ocfs2_begin_ordered_truncate(struct inode *inode,
loff_t new_size)
{
- return jbd2_journal_begin_ordered_truncate(&OCFS2_I(inode)->ip_jinode,
- new_size);
+ return jbd2_journal_begin_ordered_truncate(
+ OCFS2_SB(inode->i_sb)->journal->j_journal,
+ &OCFS2_I(inode)->ip_jinode,
+ new_size);
}
#endif /* OCFS2_JOURNAL_H */
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 5267098532bf..a1a4cfe19210 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -48,8 +48,16 @@ int seq_open(struct file *file, const struct seq_operations *op)
*/
file->f_version = 0;
- /* SEQ files support lseek, but not pread/pwrite */
- file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+ /*
+ * seq_files support lseek() and pread(). They do not implement
+ * write() at all, but we clear FMODE_PWRITE here for historical
+ * reasons.
+ *
+ * If a client of seq_files a) implements file.write() and b) wishes to
+ * support pwrite() then that client will need to implement its own
+ * file.open() which calls seq_open() and then sets FMODE_PWRITE.
+ */
+ file->f_mode &= ~FMODE_PWRITE;
return 0;
}
EXPORT_SYMBOL(seq_open);
@@ -131,6 +139,22 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
int err = 0;
mutex_lock(&m->lock);
+
+ /* Don't assume *ppos is where we left it */
+ if (unlikely(*ppos != m->read_pos)) {
+ m->read_pos = *ppos;
+ while ((err = traverse(m, *ppos)) == -EAGAIN)
+ ;
+ if (err) {
+ /* With prejudice... */
+ m->read_pos = 0;
+ m->version = 0;
+ m->index = 0;
+ m->count = 0;
+ goto Done;
+ }
+ }
+
/*
* seq_file->op->..m_start/m_stop/m_next may do special actions
* or optimisations based on the file->f_version, so we want to
@@ -230,8 +254,10 @@ Fill:
Done:
if (!copied)
copied = err;
- else
+ else {
*ppos += copied;
+ m->read_pos += copied;
+ }
file->f_version = m->version;
mutex_unlock(&m->lock);
return copied;
@@ -266,16 +292,18 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin)
if (offset < 0)
break;
retval = offset;
- if (offset != file->f_pos) {
+ if (offset != m->read_pos) {
while ((retval=traverse(m, offset)) == -EAGAIN)
;
if (retval) {
/* with extreme prejudice... */
file->f_pos = 0;
+ m->read_pos = 0;
m->version = 0;
m->index = 0;
m->count = 0;
} else {
+ m->read_pos = offset;
retval = file->f_pos = offset;
}
}
diff --git a/fs/super.c b/fs/super.c
index 61dce001dd57..8349ed6b1412 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -82,7 +82,22 @@ static struct super_block *alloc_super(struct file_system_type *type)
* lock ordering than usbfs:
*/
lockdep_set_class(&s->s_lock, &type->s_lock_key);
- down_write(&s->s_umount);
+ /*
+ * sget() can have s_umount recursion.
+ *
+ * When it cannot find a suitable sb, it allocates a new
+ * one (this one), and tries again to find a suitable old
+ * one.
+ *
+ * In case that succeeds, it will acquire the s_umount
+ * lock of the old one. Since these are clearly distrinct
+ * locks, and this object isn't exposed yet, there's no
+ * risk of deadlocks.
+ *
+ * Annotate this by putting this lock in a different
+ * subclass.
+ */
+ down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING);
s->s_count = S_BIAS;
atomic_set(&s->s_active, 1);
mutex_init(&s->s_vfs_rename_mutex);
diff --git a/fs/timerfd.c b/fs/timerfd.c
index 6a123b8ff3f5..b042bd7034b1 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -186,10 +186,9 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC);
BUILD_BUG_ON(TFD_NONBLOCK != O_NONBLOCK);
- if (flags & ~(TFD_CLOEXEC | TFD_NONBLOCK))
- return -EINVAL;
- if (clockid != CLOCK_MONOTONIC &&
- clockid != CLOCK_REALTIME)
+ if ((flags & ~TFD_CREATE_FLAGS) ||
+ (clockid != CLOCK_MONOTONIC &&
+ clockid != CLOCK_REALTIME))
return -EINVAL;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -201,7 +200,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
hrtimer_init(&ctx->tmr, clockid, HRTIMER_MODE_ABS);
ufd = anon_inode_getfd("[timerfd]", &timerfd_fops, ctx,
- flags & (O_CLOEXEC | O_NONBLOCK));
+ flags & TFD_SHARED_FCNTL_FLAGS);
if (ufd < 0)
kfree(ctx);
@@ -219,7 +218,8 @@ SYSCALL_DEFINE4(timerfd_settime, int, ufd, int, flags,
if (copy_from_user(&ktmr, utmr, sizeof(ktmr)))
return -EFAULT;
- if (!timespec_valid(&ktmr.it_value) ||
+ if ((flags & ~TFD_SETTIME_FLAGS) ||
+ !timespec_valid(&ktmr.it_value) ||
!timespec_valid(&ktmr.it_interval))
return -EINVAL;
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c
index d71dc44e21ed..cb329edc925b 100644
--- a/fs/xfs/linux-2.6/xfs_buf.c
+++ b/fs/xfs/linux-2.6/xfs_buf.c
@@ -166,6 +166,75 @@ test_page_region(
}
/*
+ * Mapping of multi-page buffers into contiguous virtual space
+ */
+
+typedef struct a_list {
+ void *vm_addr;
+ struct a_list *next;
+} a_list_t;
+
+static a_list_t *as_free_head;
+static int as_list_len;
+static DEFINE_SPINLOCK(as_lock);
+
+/*
+ * Try to batch vunmaps because they are costly.
+ */
+STATIC void
+free_address(
+ void *addr)
+{
+ a_list_t *aentry;
+
+#ifdef CONFIG_XEN
+ /*
+ * Xen needs to be able to make sure it can get an exclusive
+ * RO mapping of pages it wants to turn into a pagetable. If
+ * a newly allocated page is also still being vmap()ed by xfs,
+ * it will cause pagetable construction to fail. This is a
+ * quick workaround to always eagerly unmap pages so that Xen
+ * is happy.
+ */
+ vunmap(addr);
+ return;
+#endif
+
+ aentry = kmalloc(sizeof(a_list_t), GFP_NOWAIT);
+ if (likely(aentry)) {
+ spin_lock(&as_lock);
+ aentry->next = as_free_head;
+ aentry->vm_addr = addr;
+ as_free_head = aentry;
+ as_list_len++;
+ spin_unlock(&as_lock);
+ } else {
+ vunmap(addr);
+ }
+}
+
+STATIC void
+purge_addresses(void)
+{
+ a_list_t *aentry, *old;
+
+ if (as_free_head == NULL)
+ return;
+
+ spin_lock(&as_lock);
+ aentry = as_free_head;
+ as_free_head = NULL;
+ as_list_len = 0;
+ spin_unlock(&as_lock);
+
+ while ((old = aentry) != NULL) {
+ vunmap(aentry->vm_addr);
+ aentry = aentry->next;
+ kfree(old);
+ }
+}
+
+/*
* Internal xfs_buf_t object manipulation
*/
@@ -264,7 +333,7 @@ xfs_buf_free(
uint i;
if ((bp->b_flags & XBF_MAPPED) && (bp->b_page_count > 1))
- vm_unmap_ram(bp->b_addr - bp->b_offset, bp->b_page_count);
+ free_address(bp->b_addr - bp->b_offset);
for (i = 0; i < bp->b_page_count; i++) {
struct page *page = bp->b_pages[i];
@@ -386,8 +455,10 @@ _xfs_buf_map_pages(
bp->b_addr = page_address(bp->b_pages[0]) + bp->b_offset;
bp->b_flags |= XBF_MAPPED;
} else if (flags & XBF_MAPPED) {
- bp->b_addr = vm_map_ram(bp->b_pages, bp->b_page_count,
- -1, PAGE_KERNEL);
+ if (as_list_len > 64)
+ purge_addresses();
+ bp->b_addr = vmap(bp->b_pages, bp->b_page_count,
+ VM_MAP, PAGE_KERNEL);
if (unlikely(bp->b_addr == NULL))
return -ENOMEM;
bp->b_addr += bp->b_offset;
@@ -1672,6 +1743,8 @@ xfsbufd(
count++;
}
+ if (as_list_len > 0)
+ purge_addresses();
if (count)
blk_run_address_space(target->bt_mapping);
diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
index 83c51aba534b..e16fdb1f4f4f 100644
--- a/include/asm-frv/pgtable.h
+++ b/include/asm-frv/pgtable.h
@@ -478,7 +478,7 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
#define __swp_type(x) (((x).val >> 2) & 0x1f)
#define __swp_offset(x) ((x).val >> 8)
#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 8) })
-#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte })
+#define __pte_to_swp_entry(_pte) ((swp_entry_t) { (_pte).pte })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
static inline int pte_file(pte_t pte)
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 8190b9bcc2d9..e5f4ae989abf 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1321,6 +1321,8 @@ void drm_gem_object_free(struct kref *kref);
struct drm_gem_object *drm_gem_object_alloc(struct drm_device *dev,
size_t size);
void drm_gem_object_handle_free(struct kref *kref);
+void drm_gem_vm_open(struct vm_area_struct *vma);
+void drm_gem_vm_close(struct vm_area_struct *vma);
int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
static inline void
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index d54de24bf371..5ded1acfb543 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -609,7 +609,7 @@ extern char *drm_get_dvi_i_subconnector_name(int val);
extern char *drm_get_dvi_i_select_name(int val);
extern char *drm_get_tv_subconnector_name(int val);
extern char *drm_get_tv_select_name(int val);
-extern void drm_fb_release(struct file *filp);
+extern void drm_fb_release(struct drm_file *file_priv);
extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct drm_mode_group *group);
extern struct edid *drm_get_edid(struct drm_connector *connector,
struct i2c_adapter *adapter);
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 0c6f0e11b41b..0b0d236c2154 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -54,13 +54,13 @@ struct drm_crtc_helper_funcs {
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
/* Actually set the mode */
- void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
- struct drm_display_mode *adjusted_mode, int x, int y,
- struct drm_framebuffer *old_fb);
+ int (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
+ struct drm_display_mode *adjusted_mode, int x, int y,
+ struct drm_framebuffer *old_fb);
/* Move the crtc on the current fb to the given position *optional* */
- void (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb);
+ int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
+ struct drm_framebuffer *old_fb);
};
struct drm_encoder_helper_funcs {
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 2aa283ab062b..1b16108a5417 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -171,8 +171,6 @@ struct bio {
#define BIO_RW_FAILFAST_TRANSPORT 8
#define BIO_RW_FAILFAST_DRIVER 9
-#define BIO_RW_SYNC (BIO_RW_SYNCIO | BIO_RW_UNPLUG)
-
#define bio_rw_flagged(bio, flag) ((bio)->bi_rw & (1 << (flag)))
/*
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h
index 25379cba2370..6e915878e88c 100644
--- a/include/linux/blktrace_api.h
+++ b/include/linux/blktrace_api.h
@@ -15,6 +15,7 @@ enum blktrace_cat {
BLK_TC_WRITE = 1 << 1, /* writes */
BLK_TC_BARRIER = 1 << 2, /* barrier */
BLK_TC_SYNC = 1 << 3, /* sync IO */
+ BLK_TC_SYNCIO = BLK_TC_SYNC,
BLK_TC_QUEUE = 1 << 4, /* queueing/merging */
BLK_TC_REQUEUE = 1 << 5, /* requeueing */
BLK_TC_ISSUE = 1 << 6, /* issue */
diff --git a/include/linux/device.h b/include/linux/device.h
index 45e5b1921fbb..47f343c7bdda 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -147,6 +147,8 @@ extern void put_driver(struct device_driver *drv);
extern struct device_driver *driver_find(const char *name,
struct bus_type *bus);
extern int driver_probe_done(void);
+extern int wait_for_device_probe(void);
+
/* sysfs interface for exporting driver attributes */
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 3e68469c1885..f0413845f20e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -121,6 +121,7 @@ struct dma_chan_percpu {
* @local: per-cpu pointer to a struct dma_chan_percpu
* @client-count: how many clients are using this channel
* @table_count: number of appearances in the mem-to-mem allocation table
+ * @private: private data for certain client-channel associations
*/
struct dma_chan {
struct dma_device *device;
@@ -134,6 +135,7 @@ struct dma_chan {
struct dma_chan_percpu *local;
int client_count;
int table_count;
+ void *private;
};
/**
diff --git a/include/linux/firmware-map.h b/include/linux/firmware-map.h
index 6e199c8dfacc..cca686b39123 100644
--- a/include/linux/firmware-map.h
+++ b/include/linux/firmware-map.h
@@ -1,7 +1,7 @@
/*
* include/linux/firmware-map.h:
* Copyright (C) 2008 SUSE LINUX Products GmbH
- * by Bernhard Walle <bwalle@suse.de>
+ * by Bernhard Walle <bernhard.walle@gmx.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License v2.0 as published by
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 6022f44043f2..92734c0012e6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -54,24 +54,30 @@ struct inodes_stat_t {
#define MAY_ACCESS 16
#define MAY_OPEN 32
+/*
+ * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond
+ * to O_WRONLY and O_RDWR via the strange trick in __dentry_open()
+ */
+
/* file is open for reading */
#define FMODE_READ ((__force fmode_t)1)
/* file is open for writing */
#define FMODE_WRITE ((__force fmode_t)2)
/* file is seekable */
#define FMODE_LSEEK ((__force fmode_t)4)
-/* file can be accessed using pread/pwrite */
+/* file can be accessed using pread */
#define FMODE_PREAD ((__force fmode_t)8)
-#define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */
+/* file can be accessed using pwrite */
+#define FMODE_PWRITE ((__force fmode_t)16)
/* File is opened for execution with sys_execve / sys_uselib */
-#define FMODE_EXEC ((__force fmode_t)16)
+#define FMODE_EXEC ((__force fmode_t)32)
/* File is opened with O_NDELAY (only set for block devices) */
-#define FMODE_NDELAY ((__force fmode_t)32)
+#define FMODE_NDELAY ((__force fmode_t)64)
/* File is opened with O_EXCL (only set for block devices) */
-#define FMODE_EXCL ((__force fmode_t)64)
+#define FMODE_EXCL ((__force fmode_t)128)
/* File is opened using open(.., 3, ..) and is writeable only for ioctls
(specialy hack for floppy.c) */
-#define FMODE_WRITE_IOCTL ((__force fmode_t)128)
+#define FMODE_WRITE_IOCTL ((__force fmode_t)256)
/*
* Don't update ctime and mtime.
@@ -87,10 +93,10 @@ struct inodes_stat_t {
#define WRITE 1
#define READA 2 /* read-ahead - don't block if no resources */
#define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */
-#define READ_SYNC (READ | (1 << BIO_RW_SYNC))
+#define READ_SYNC (READ | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG))
#define READ_META (READ | (1 << BIO_RW_META))
-#define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC))
-#define SWRITE_SYNC (SWRITE | (1 << BIO_RW_SYNC))
+#define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG))
+#define SWRITE_SYNC (SWRITE | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG))
#define WRITE_BARRIER (WRITE | (1 << BIO_RW_BARRIER))
#define DISCARD_NOBARRIER (1 << BIO_RW_DISCARD)
#define DISCARD_BARRIER ((1 << BIO_RW_DISCARD) | (1 << BIO_RW_BARRIER))
diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h
index b28b37eb11c6..4d248b3f1323 100644
--- a/include/linux/jbd2.h
+++ b/include/linux/jbd2.h
@@ -1150,7 +1150,8 @@ extern int jbd2_journal_clear_err (journal_t *);
extern int jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *);
extern int jbd2_journal_force_commit(journal_t *);
extern int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *inode);
-extern int jbd2_journal_begin_ordered_truncate(struct jbd2_inode *inode, loff_t new_size);
+extern int jbd2_journal_begin_ordered_truncate(journal_t *journal,
+ struct jbd2_inode *inode, loff_t new_size);
extern void jbd2_journal_init_jbd_inode(struct jbd2_inode *jinode, struct inode *inode);
extern void jbd2_journal_release_jbd_inode(journal_t *journal, struct jbd2_inode *jinode);
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 32851eef48f0..2ec6cc14a114 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -182,6 +182,14 @@ struct kprobe_blackpoint {
DECLARE_PER_CPU(struct kprobe *, current_kprobe);
DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
+/*
+ * For #ifdef avoidance:
+ */
+static inline int kprobes_built_in(void)
+{
+ return 1;
+}
+
#ifdef CONFIG_KRETPROBES
extern void arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs);
@@ -271,8 +279,16 @@ void unregister_kretprobes(struct kretprobe **rps, int num);
void kprobe_flush_task(struct task_struct *tk);
void recycle_rp_inst(struct kretprobe_instance *ri, struct hlist_head *head);
-#else /* CONFIG_KPROBES */
+#else /* !CONFIG_KPROBES: */
+static inline int kprobes_built_in(void)
+{
+ return 0;
+}
+static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+{
+ return 0;
+}
static inline struct kprobe *get_kprobe(void *addr)
{
return NULL;
@@ -329,5 +345,5 @@ static inline void unregister_kretprobes(struct kretprobe **rps, int num)
static inline void kprobe_flush_task(struct task_struct *tk)
{
}
-#endif /* CONFIG_KPROBES */
-#endif /* _LINUX_KPROBES_H */
+#endif /* CONFIG_KPROBES */
+#endif /* _LINUX_KPROBES_H */
diff --git a/include/linux/kvm.h b/include/linux/kvm.h
index 5715f1907601..0424326f1679 100644
--- a/include/linux/kvm.h
+++ b/include/linux/kvm.h
@@ -58,10 +58,10 @@ struct kvm_irqchip {
__u32 pad;
union {
char dummy[512]; /* reserving space */
-#ifdef CONFIG_X86
+#ifdef __KVM_HAVE_PIT
struct kvm_pic_state pic;
#endif
-#if defined(CONFIG_X86) || defined(CONFIG_IA64)
+#ifdef __KVM_HAVE_IOAPIC
struct kvm_ioapic_state ioapic;
#endif
} chip;
@@ -384,16 +384,16 @@ struct kvm_trace_rec {
#define KVM_CAP_MP_STATE 14
#define KVM_CAP_COALESCED_MMIO 15
#define KVM_CAP_SYNC_MMU 16 /* Changes to host mmap are reflected in guest */
-#if defined(CONFIG_X86)||defined(CONFIG_IA64)
+#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT
#define KVM_CAP_DEVICE_ASSIGNMENT 17
#endif
#define KVM_CAP_IOMMU 18
-#if defined(CONFIG_X86)
+#ifdef __KVM_HAVE_MSI
#define KVM_CAP_DEVICE_MSI 20
#endif
/* Bug in KVM_SET_USER_MEMORY_REGION fixed: */
#define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21
-#if defined(CONFIG_X86)
+#ifdef __KVM_HAVE_USER_NMI
#define KVM_CAP_USER_NMI 22
#endif
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ec49d0be7f52..bf6f703642fc 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -285,6 +285,7 @@ void kvm_free_physmem(struct kvm *kvm);
struct kvm *kvm_arch_create_vm(void);
void kvm_arch_destroy_vm(struct kvm *kvm);
void kvm_free_all_assigned_devices(struct kvm *kvm);
+void kvm_arch_sync_events(struct kvm *kvm);
int kvm_cpu_get_interrupt(struct kvm_vcpu *v);
int kvm_cpu_has_interrupt(struct kvm_vcpu *v);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 7dc04ff5ab89..065cdf8c09fb 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1041,10 +1041,23 @@ extern void free_bootmem_with_active_regions(int nid,
typedef int (*work_fn_t)(unsigned long, unsigned long, void *);
extern void work_with_active_regions(int nid, work_fn_t work_fn, void *data);
extern void sparse_memory_present_with_active_regions(int nid);
-#ifndef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
-extern int early_pfn_to_nid(unsigned long pfn);
-#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */
+
+#if !defined(CONFIG_ARCH_POPULATES_NODE_MAP) && \
+ !defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID)
+static inline int __early_pfn_to_nid(unsigned long pfn)
+{
+ return 0;
+}
+#else
+/* please see mm/page_alloc.c */
+extern int __meminit early_pfn_to_nid(unsigned long pfn);
+#ifdef CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID
+/* there is a per-arch backend function. */
+extern int __meminit __early_pfn_to_nid(unsigned long pfn);
+#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+#endif
+
extern void set_dma_reserve(unsigned long new_dma_reserve);
extern void memmap_init_zone(unsigned long, int, unsigned long,
unsigned long, enum memmap_context);
@@ -1159,6 +1172,7 @@ extern int filemap_fault(struct vm_area_struct *, struct vm_fault *);
/* mm/page-writeback.c */
int write_one_page(struct page *page, int wait);
+void task_dirty_inc(struct task_struct *tsk);
/* readahead.c */
#define VM_MAX_READAHEAD 128 /* kbytes */
diff --git a/include/linux/mmiotrace.h b/include/linux/mmiotrace.h
index 139d7c88d9c9..3d1b7bde1283 100644
--- a/include/linux/mmiotrace.h
+++ b/include/linux/mmiotrace.h
@@ -1,5 +1,5 @@
-#ifndef MMIOTRACE_H
-#define MMIOTRACE_H
+#ifndef _LINUX_MMIOTRACE_H
+#define _LINUX_MMIOTRACE_H
#include <linux/types.h>
#include <linux/list.h>
@@ -13,28 +13,34 @@ typedef void (*kmmio_post_handler_t)(struct kmmio_probe *,
unsigned long condition, struct pt_regs *);
struct kmmio_probe {
- struct list_head list; /* kmmio internal list */
- unsigned long addr; /* start location of the probe point */
- unsigned long len; /* length of the probe region */
- kmmio_pre_handler_t pre_handler; /* Called before addr is executed. */
- kmmio_post_handler_t post_handler; /* Called after addr is executed */
- void *private;
+ /* kmmio internal list: */
+ struct list_head list;
+ /* start location of the probe point: */
+ unsigned long addr;
+ /* length of the probe region: */
+ unsigned long len;
+ /* Called before addr is executed: */
+ kmmio_pre_handler_t pre_handler;
+ /* Called after addr is executed: */
+ kmmio_post_handler_t post_handler;
+ void *private;
};
+extern unsigned int kmmio_count;
+
+extern int register_kmmio_probe(struct kmmio_probe *p);
+extern void unregister_kmmio_probe(struct kmmio_probe *p);
+
+#ifdef CONFIG_MMIOTRACE
/* kmmio is active by some kmmio_probes? */
static inline int is_kmmio_active(void)
{
- extern unsigned int kmmio_count;
return kmmio_count;
}
-extern int register_kmmio_probe(struct kmmio_probe *p);
-extern void unregister_kmmio_probe(struct kmmio_probe *p);
-
/* Called from page fault handler. */
extern int kmmio_handler(struct pt_regs *regs, unsigned long addr);
-#ifdef CONFIG_MMIOTRACE
/* Called from ioremap.c */
extern void mmiotrace_ioremap(resource_size_t offset, unsigned long size,
void __iomem *addr);
@@ -43,7 +49,17 @@ extern void mmiotrace_iounmap(volatile void __iomem *addr);
/* For anyone to insert markers. Remember trailing newline. */
extern int mmiotrace_printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
-#else
+#else /* !CONFIG_MMIOTRACE: */
+static inline int is_kmmio_active(void)
+{
+ return 0;
+}
+
+static inline int kmmio_handler(struct pt_regs *regs, unsigned long addr)
+{
+ return 0;
+}
+
static inline void mmiotrace_ioremap(resource_size_t offset,
unsigned long size, void __iomem *addr)
{
@@ -63,28 +79,28 @@ static inline int mmiotrace_printk(const char *fmt, ...)
#endif /* CONFIG_MMIOTRACE */
enum mm_io_opcode {
- MMIO_READ = 0x1, /* struct mmiotrace_rw */
- MMIO_WRITE = 0x2, /* struct mmiotrace_rw */
- MMIO_PROBE = 0x3, /* struct mmiotrace_map */
- MMIO_UNPROBE = 0x4, /* struct mmiotrace_map */
- MMIO_UNKNOWN_OP = 0x5, /* struct mmiotrace_rw */
+ MMIO_READ = 0x1, /* struct mmiotrace_rw */
+ MMIO_WRITE = 0x2, /* struct mmiotrace_rw */
+ MMIO_PROBE = 0x3, /* struct mmiotrace_map */
+ MMIO_UNPROBE = 0x4, /* struct mmiotrace_map */
+ MMIO_UNKNOWN_OP = 0x5, /* struct mmiotrace_rw */
};
struct mmiotrace_rw {
- resource_size_t phys; /* PCI address of register */
- unsigned long value;
- unsigned long pc; /* optional program counter */
- int map_id;
- unsigned char opcode; /* one of MMIO_{READ,WRITE,UNKNOWN_OP} */
- unsigned char width; /* size of register access in bytes */
+ resource_size_t phys; /* PCI address of register */
+ unsigned long value;
+ unsigned long pc; /* optional program counter */
+ int map_id;
+ unsigned char opcode; /* one of MMIO_{READ,WRITE,UNKNOWN_OP} */
+ unsigned char width; /* size of register access in bytes */
};
struct mmiotrace_map {
- resource_size_t phys; /* base address in PCI space */
- unsigned long virt; /* base virtual address */
- unsigned long len; /* mapping size */
- int map_id;
- unsigned char opcode; /* MMIO_PROBE or MMIO_UNPROBE */
+ resource_size_t phys; /* base address in PCI space */
+ unsigned long virt; /* base virtual address */
+ unsigned long len; /* mapping size */
+ int map_id;
+ unsigned char opcode; /* MMIO_PROBE or MMIO_UNPROBE */
};
/* in kernel/trace/trace_mmiotrace.c */
@@ -94,4 +110,4 @@ extern void mmio_trace_rw(struct mmiotrace_rw *rw);
extern void mmio_trace_mapping(struct mmiotrace_map *map);
extern int mmio_trace_printk(const char *fmt, va_list args);
-#endif /* MMIOTRACE_H */
+#endif /* _LINUX_MMIOTRACE_H */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 09c14e213b63..1aca6cebbb78 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -1071,7 +1071,7 @@ void sparse_init(void);
#endif /* CONFIG_SPARSEMEM */
#ifdef CONFIG_NODES_SPAN_OTHER_NODES
-#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid))
+bool early_pfn_in_nid(unsigned long pfn, int nid);
#else
#define early_pfn_in_nid(pfn, nid) (1)
#endif
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 52a9fe08451c..aca8c458aa8a 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1312,6 +1312,7 @@
#define PCI_DEVICE_ID_VIA_VT3351 0x0351
#define PCI_DEVICE_ID_VIA_VT3364 0x0364
#define PCI_DEVICE_ID_VIA_8371_0 0x0391
+#define PCI_DEVICE_ID_VIA_6415 0x0415
#define PCI_DEVICE_ID_VIA_8501_0 0x0501
#define PCI_DEVICE_ID_VIA_82C561 0x0561
#define PCI_DEVICE_ID_VIA_82C586_1 0x0571
@@ -1444,6 +1445,7 @@
#define PCI_DEVICE_ID_DIGI_DF_M_E 0x0071
#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A 0x0072
#define PCI_DEVICE_ID_DIGI_DF_M_A 0x0073
+#define PCI_DEVICE_ID_DIGI_NEO_8 0x00B1
#define PCI_DEVICE_ID_NEO_2DB9 0x00C8
#define PCI_DEVICE_ID_NEO_2DB9PRI 0x00C9
#define PCI_DEVICE_ID_NEO_2RJ45 0x00CA
@@ -2321,6 +2323,9 @@
#define PCI_DEVICE_ID_INTEL_82378 0x0484
#define PCI_DEVICE_ID_INTEL_I960 0x0960
#define PCI_DEVICE_ID_INTEL_I960RM 0x0962
+#define PCI_DEVICE_ID_INTEL_8257X_SOL 0x1062
+#define PCI_DEVICE_ID_INTEL_82573E_SOL 0x1085
+#define PCI_DEVICE_ID_INTEL_82573L_SOL 0x108F
#define PCI_DEVICE_ID_INTEL_82815_MC 0x1130
#define PCI_DEVICE_ID_INTEL_82815_CGC 0x1132
#define PCI_DEVICE_ID_INTEL_82092AA_0 0x1221
diff --git a/include/linux/pm.h b/include/linux/pm.h
index de2e0a8f6728..24ba5f67b3a3 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -381,10 +381,12 @@ struct dev_pm_info {
#ifdef CONFIG_PM_SLEEP
extern void device_pm_lock(void);
+extern int sysdev_resume(void);
extern void device_power_up(pm_message_t state);
extern void device_resume(pm_message_t state);
extern void device_pm_unlock(void);
+extern int sysdev_suspend(pm_message_t state);
extern int device_power_down(pm_message_t state);
extern int device_suspend(pm_message_t state);
extern int device_prepare_suspend(pm_message_t state);
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index 40ea5058c2ec..f616f31576d7 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -19,6 +19,7 @@ struct seq_file {
size_t from;
size_t count;
loff_t index;
+ loff_t read_pos;
u64 version;
struct mutex lock;
const struct seq_operations *op;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 90bbbf0b1161..df9245c7bd3b 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -296,6 +296,7 @@ struct uart_port {
#define UPF_HARDPPS_CD ((__force upf_t) (1 << 11))
#define UPF_LOW_LATENCY ((__force upf_t) (1 << 13))
#define UPF_BUGGY_UART ((__force upf_t) (1 << 14))
+#define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15))
#define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16))
#define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
diff --git a/include/linux/slab.h b/include/linux/slab.h
index f96d13c281e8..24c5602bee99 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -127,6 +127,7 @@ int kmem_ptr_validate(struct kmem_cache *cachep, const void *ptr);
void * __must_check __krealloc(const void *, size_t, gfp_t);
void * __must_check krealloc(const void *, size_t, gfp_t);
void kfree(const void *);
+void kzfree(const void *);
size_t ksize(const void *);
/*
diff --git a/include/linux/spi/spi_bitbang.h b/include/linux/spi/spi_bitbang.h
index bf8de281b4ed..eed4254bd503 100644
--- a/include/linux/spi/spi_bitbang.h
+++ b/include/linux/spi/spi_bitbang.h
@@ -83,6 +83,13 @@ extern int spi_bitbang_stop(struct spi_bitbang *spi);
* int getmiso(struct spi_device *);
* void spidelay(unsigned);
*
+ * setsck()'s is_on parameter is a zero/nonzero boolean.
+ *
+ * setmosi()'s is_on parameter is a zero/nonzero boolean.
+ *
+ * getmiso() is required to return 0 or 1 only. Any other value is invalid
+ * and will result in improper operation.
+ *
* A non-inlined routine would call bitbang_txrx_*() routines. The
* main loop could easily compile down to a handful of instructions,
* especially if the delay is a NOP (to run at peak speed).
diff --git a/include/linux/timerfd.h b/include/linux/timerfd.h
index 86cb0501d3e2..2d0792983f8c 100644
--- a/include/linux/timerfd.h
+++ b/include/linux/timerfd.h
@@ -11,13 +11,21 @@
/* For O_CLOEXEC and O_NONBLOCK */
#include <linux/fcntl.h>
-/* Flags for timerfd_settime. */
+/*
+ * CAREFUL: Check include/asm-generic/fcntl.h when defining
+ * new flags, since they might collide with O_* ones. We want
+ * to re-use O_* flags that couldn't possibly have a meaning
+ * from eventfd, in order to leave a free define-space for
+ * shared O_* flags.
+ */
#define TFD_TIMER_ABSTIME (1 << 0)
-
-/* Flags for timerfd_create. */
#define TFD_CLOEXEC O_CLOEXEC
#define TFD_NONBLOCK O_NONBLOCK
+#define TFD_SHARED_FCNTL_FLAGS (TFD_CLOEXEC | TFD_NONBLOCK)
+/* Flags for timerfd_create. */
+#define TFD_CREATE_FLAGS TFD_SHARED_FCNTL_FLAGS
+/* Flags for timerfd_settime. */
+#define TFD_SETTIME_FLAGS TFD_TIMER_ABSTIME
#endif /* _LINUX_TIMERFD_H */
-
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 506e7620a986..9c0890c7a06a 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -84,6 +84,10 @@ extern struct vm_struct *get_vm_area_caller(unsigned long size,
unsigned long flags, void *caller);
extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
unsigned long start, unsigned long end);
+extern struct vm_struct *__get_vm_area_caller(unsigned long size,
+ unsigned long flags,
+ unsigned long start, unsigned long end,
+ void *caller);
extern struct vm_struct *get_vm_area_node(unsigned long size,
unsigned long flags, int node,
gfp_t gfp_mask);
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 708105e163df..8d4ff5afc1d8 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -370,10 +370,14 @@ void __init prepare_namespace(void)
ssleep(root_delay);
}
- /* wait for the known devices to complete their probing */
- while (driver_probe_done() != 0)
- msleep(100);
- async_synchronize_full();
+ /*
+ * wait for the known devices to complete their probing
+ *
+ * Note: this is a potential source of long boot delays.
+ * For example, it is not atypical to wait 5 seconds here
+ * for the touchpad of a laptop to initialize.
+ */
+ wait_for_device_probe();
md_run_setup();
@@ -399,6 +403,7 @@ void __init prepare_namespace(void)
while (driver_probe_done() != 0 ||
(ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
msleep(100);
+ async_synchronize_full();
}
is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c
index ff95e3192884..9bdddbcb3d6a 100644
--- a/init/do_mounts_md.c
+++ b/init/do_mounts_md.c
@@ -281,8 +281,9 @@ static void __init autodetect_raid(void)
*/
printk(KERN_INFO "md: Waiting for all devices to be available before autodetect\n");
printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n");
- while (driver_probe_done() < 0)
- msleep(100);
+
+ wait_for_device_probe();
+
fd = sys_open("/dev/md0", 0, 0);
if (fd >= 0) {
sys_ioctl(fd, RAID_AUTORUN, raid_autopart);
diff --git a/kernel/Makefile b/kernel/Makefile
index 170a9213c1b6..e4791b3ba55d 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -51,6 +51,7 @@ obj-$(CONFIG_UID16) += uid16.o
obj-$(CONFIG_MODULES) += module.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_PM) += power/
+obj-$(CONFIG_FREEZER) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index e14db9c089b9..9edb5c4b79b4 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1122,8 +1122,8 @@ static void cgroup_kill_sb(struct super_block *sb) {
mutex_unlock(&cgroup_mutex);
- kfree(root);
kill_litter_super(sb);
+ kfree(root);
}
static struct file_system_type cgroup_fs_type = {
diff --git a/kernel/futex.c b/kernel/futex.c
index f89d373a9c6d..438701adce23 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1165,6 +1165,7 @@ static int futex_wait(u32 __user *uaddr, int fshared,
u32 val, ktime_t *abs_time, u32 bitset, int clockrt)
{
struct task_struct *curr = current;
+ struct restart_block *restart;
DECLARE_WAITQUEUE(wait, curr);
struct futex_hash_bucket *hb;
struct futex_q q;
@@ -1216,11 +1217,13 @@ retry:
if (!ret)
goto retry;
- return ret;
+ goto out;
}
ret = -EWOULDBLOCK;
- if (uval != val)
- goto out_unlock_put_key;
+ if (unlikely(uval != val)) {
+ queue_unlock(&q, hb);
+ goto out_put_key;
+ }
/* Only actually queue if *uaddr contained val. */
queue_me(&q, hb);
@@ -1284,38 +1287,38 @@ retry:
*/
/* If we were woken (and unqueued), we succeeded, whatever. */
+ ret = 0;
if (!unqueue_me(&q))
- return 0;
+ goto out_put_key;
+ ret = -ETIMEDOUT;
if (rem)
- return -ETIMEDOUT;
+ goto out_put_key;
/*
* We expect signal_pending(current), but another thread may
* have handled it for us already.
*/
+ ret = -ERESTARTSYS;
if (!abs_time)
- return -ERESTARTSYS;
- else {
- struct restart_block *restart;
- restart = &current_thread_info()->restart_block;
- restart->fn = futex_wait_restart;
- restart->futex.uaddr = (u32 *)uaddr;
- restart->futex.val = val;
- restart->futex.time = abs_time->tv64;
- restart->futex.bitset = bitset;
- restart->futex.flags = 0;
-
- if (fshared)
- restart->futex.flags |= FLAGS_SHARED;
- if (clockrt)
- restart->futex.flags |= FLAGS_CLOCKRT;
- return -ERESTART_RESTARTBLOCK;
- }
+ goto out_put_key;
-out_unlock_put_key:
- queue_unlock(&q, hb);
- put_futex_key(fshared, &q.key);
+ restart = &current_thread_info()->restart_block;
+ restart->fn = futex_wait_restart;
+ restart->futex.uaddr = (u32 *)uaddr;
+ restart->futex.val = val;
+ restart->futex.time = abs_time->tv64;
+ restart->futex.bitset = bitset;
+ restart->futex.flags = 0;
+
+ if (fshared)
+ restart->futex.flags |= FLAGS_SHARED;
+ if (clockrt)
+ restart->futex.flags |= FLAGS_CLOCKRT;
+ ret = -ERESTART_RESTARTBLOCK;
+
+out_put_key:
+ put_futex_key(fshared, &q.key);
out:
return ret;
}
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 795e7b67a228..c7fd6692939d 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1465,6 +1465,11 @@ int kernel_kexec(void)
error = device_power_down(PMSG_FREEZE);
if (error)
goto Enable_irqs;
+
+ /* Suspend system devices */
+ error = sysdev_suspend(PMSG_FREEZE);
+ if (error)
+ goto Power_up_devices;
} else
#endif
{
@@ -1477,6 +1482,8 @@ int kernel_kexec(void)
#ifdef CONFIG_KEXEC_JUMP
if (kexec_image->preserve_context) {
+ sysdev_resume();
+ Power_up_devices:
device_power_up(PMSG_RESTORE);
Enable_irqs:
local_irq_enable();
diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
index 2313a4cc14ea..e976e505648d 100644
--- a/kernel/posix-cpu-timers.c
+++ b/kernel/posix-cpu-timers.c
@@ -681,6 +681,33 @@ static void cpu_timer_fire(struct k_itimer *timer)
}
/*
+ * Sample a process (thread group) timer for the given group_leader task.
+ * Must be called with tasklist_lock held for reading.
+ */
+static int cpu_timer_sample_group(const clockid_t which_clock,
+ struct task_struct *p,
+ union cpu_time_count *cpu)
+{
+ struct task_cputime cputime;
+
+ thread_group_cputimer(p, &cputime);
+ switch (CPUCLOCK_WHICH(which_clock)) {
+ default:
+ return -EINVAL;
+ case CPUCLOCK_PROF:
+ cpu->cpu = cputime_add(cputime.utime, cputime.stime);
+ break;
+ case CPUCLOCK_VIRT:
+ cpu->cpu = cputime.utime;
+ break;
+ case CPUCLOCK_SCHED:
+ cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p);
+ break;
+ }
+ return 0;
+}
+
+/*
* Guts of sys_timer_settime for CPU timers.
* This is called with the timer locked and interrupts disabled.
* If we return TIMER_RETRY, it's necessary to release the timer's lock
@@ -741,7 +768,7 @@ int posix_cpu_timer_set(struct k_itimer *timer, int flags,
if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
cpu_clock_sample(timer->it_clock, p, &val);
} else {
- cpu_clock_sample_group(timer->it_clock, p, &val);
+ cpu_timer_sample_group(timer->it_clock, p, &val);
}
if (old) {
@@ -889,7 +916,7 @@ void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
read_unlock(&tasklist_lock);
goto dead;
} else {
- cpu_clock_sample_group(timer->it_clock, p, &now);
+ cpu_timer_sample_group(timer->it_clock, p, &now);
clear_dead = (unlikely(p->exit_state) &&
thread_group_empty(p));
}
@@ -1244,7 +1271,7 @@ void posix_cpu_timer_schedule(struct k_itimer *timer)
clear_dead_task(timer, now);
goto out_unlock;
}
- cpu_clock_sample_group(timer->it_clock, p, &now);
+ cpu_timer_sample_group(timer->it_clock, p, &now);
bump_cpu_timer(timer, now);
/* Leave the tasklist_lock locked for the call below. */
}
@@ -1409,33 +1436,6 @@ void run_posix_cpu_timers(struct task_struct *tsk)
}
/*
- * Sample a process (thread group) timer for the given group_leader task.
- * Must be called with tasklist_lock held for reading.
- */
-static int cpu_timer_sample_group(const clockid_t which_clock,
- struct task_struct *p,
- union cpu_time_count *cpu)
-{
- struct task_cputime cputime;
-
- thread_group_cputimer(p, &cputime);
- switch (CPUCLOCK_WHICH(which_clock)) {
- default:
- return -EINVAL;
- case CPUCLOCK_PROF:
- cpu->cpu = cputime_add(cputime.utime, cputime.stime);
- break;
- case CPUCLOCK_VIRT:
- cpu->cpu = cputime.utime;
- break;
- case CPUCLOCK_SCHED:
- cpu->sched = cputime.sum_exec_runtime + task_delta_exec(p);
- break;
- }
- return 0;
-}
-
-/*
* Set one of the process-wide special case CPU timers.
* The tsk->sighand->siglock must be held by the caller.
* The *newval argument is relative and we update it to be absolute, *oldval
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index d7a10167a25b..720ea4f781bd 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -3,7 +3,7 @@ ifeq ($(CONFIG_PM_DEBUG),y)
EXTRA_CFLAGS += -DDEBUG
endif
-obj-y := main.o
+obj-$(CONFIG_PM) += main.o
obj-$(CONFIG_PM_SLEEP) += console.o
obj-$(CONFIG_FREEZER) += process.o
obj-$(CONFIG_HIBERNATION) += swsusp.o disk.o snapshot.o swap.o user.o
diff --git a/kernel/power/console.c b/kernel/power/console.c
index b8628be2a465..a3961b205de7 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -78,6 +78,12 @@ void pm_restore_console(void)
}
set_console(orig_fgconsole);
release_console_sem();
+
+ if (vt_waitactive(orig_fgconsole)) {
+ pr_debug("Resume: Can't switch VCs.");
+ return;
+ }
+
kmsg_redirect = orig_kmsg;
}
#endif
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 432ee575c9ee..4a4a206b1979 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -227,6 +227,12 @@ static int create_image(int platform_mode)
"aborting hibernation\n");
goto Enable_irqs;
}
+ sysdev_suspend(PMSG_FREEZE);
+ if (error) {
+ printk(KERN_ERR "PM: Some devices failed to power down, "
+ "aborting hibernation\n");
+ goto Power_up_devices;
+ }
if (hibernation_test(TEST_CORE))
goto Power_up;
@@ -242,9 +248,11 @@ static int create_image(int platform_mode)
if (!in_suspend)
platform_leave(platform_mode);
Power_up:
+ sysdev_resume();
/* NOTE: device_power_up() is just a resume() for devices
* that suspended with irqs off ... no overall powerup.
*/
+ Power_up_devices:
device_power_up(in_suspend ?
(error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
Enable_irqs:
@@ -335,6 +343,7 @@ static int resume_target_kernel(void)
"aborting resume\n");
goto Enable_irqs;
}
+ sysdev_suspend(PMSG_QUIESCE);
/* We'll ignore saved state, but this gets preempt count (etc) right */
save_processor_state();
error = restore_highmem();
@@ -357,6 +366,7 @@ static int resume_target_kernel(void)
swsusp_free();
restore_processor_state();
touch_softlockup_watchdog();
+ sysdev_resume();
device_power_up(PMSG_RECOVER);
Enable_irqs:
local_irq_enable();
@@ -440,6 +450,7 @@ int hibernation_platform_enter(void)
local_irq_disable();
error = device_power_down(PMSG_HIBERNATE);
if (!error) {
+ sysdev_suspend(PMSG_HIBERNATE);
hibernation_ops->enter();
/* We should never get here */
while (1);
@@ -595,6 +606,12 @@ static int software_resume(void)
unsigned int flags;
/*
+ * If the user said "noresume".. bail out early.
+ */
+ if (noresume)
+ return 0;
+
+ /*
* name_to_dev_t() below takes a sysfs buffer mutex when sysfs
* is configured into the kernel. Since the regular hibernate
* trigger path is via sysfs which takes a buffer mutex before
@@ -610,6 +627,11 @@ static int software_resume(void)
mutex_unlock(&pm_mutex);
return -ENOENT;
}
+ /*
+ * Some device discovery might still be in progress; we need
+ * to wait for this to finish.
+ */
+ wait_for_device_probe();
swsusp_resume_device = name_to_dev_t(resume_file);
pr_debug("PM: Resume from partition %s\n", resume_file);
} else {
diff --git a/kernel/power/main.c b/kernel/power/main.c
index b4d219016b6c..c9632f841f64 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -298,8 +298,12 @@ static int suspend_enter(suspend_state_t state)
goto Done;
}
- if (!suspend_test(TEST_CORE))
- error = suspend_ops->enter(state);
+ error = sysdev_suspend(PMSG_SUSPEND);
+ if (!error) {
+ if (!suspend_test(TEST_CORE))
+ error = suspend_ops->enter(state);
+ sysdev_resume();
+ }
device_power_up(PMSG_RESUME);
Done:
diff --git a/kernel/power/swap.c b/kernel/power/swap.c
index 6da14358537c..505f319e489c 100644
--- a/kernel/power/swap.c
+++ b/kernel/power/swap.c
@@ -60,6 +60,7 @@ static struct block_device *resume_bdev;
static int submit(int rw, pgoff_t page_off, struct page *page,
struct bio **bio_chain)
{
+ const int bio_rw = rw | (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
struct bio *bio;
bio = bio_alloc(__GFP_WAIT | __GFP_HIGH, 1);
@@ -80,7 +81,7 @@ static int submit(int rw, pgoff_t page_off, struct page *page,
bio_get(bio);
if (bio_chain == NULL) {
- submit_bio(rw | (1 << BIO_RW_SYNC), bio);
+ submit_bio(bio_rw, bio);
wait_on_page_locked(page);
if (rw == READ)
bio_set_pages_dirty(bio);
@@ -90,7 +91,7 @@ static int submit(int rw, pgoff_t page_off, struct page *page,
get_page(page); /* These pages are freed later */
bio->bi_private = *bio_chain;
*bio_chain = bio;
- submit_bio(rw | (1 << BIO_RW_SYNC), bio);
+ submit_bio(bio_rw, bio);
}
return 0;
}
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 005b93d839ba..6c85359364f2 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -95,15 +95,15 @@ static int snapshot_open(struct inode *inode, struct file *filp)
data->swap = swsusp_resume_device ?
swap_type_of(swsusp_resume_device, 0, NULL) : -1;
data->mode = O_RDONLY;
- error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
+ error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
if (error)
- pm_notifier_call_chain(PM_POST_RESTORE);
+ pm_notifier_call_chain(PM_POST_HIBERNATION);
} else {
data->swap = -1;
data->mode = O_WRONLY;
- error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
+ error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
if (error)
- pm_notifier_call_chain(PM_POST_HIBERNATION);
+ pm_notifier_call_chain(PM_POST_RESTORE);
}
if (error)
atomic_inc(&snapshot_device_available);
diff --git a/kernel/printk.c b/kernel/printk.c
index 69188f226a93..e3602d0755b0 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -73,7 +73,6 @@ EXPORT_SYMBOL(oops_in_progress);
* driver system.
*/
static DECLARE_MUTEX(console_sem);
-static DECLARE_MUTEX(secondary_console_sem);
struct console *console_drivers;
EXPORT_SYMBOL_GPL(console_drivers);
@@ -891,12 +890,14 @@ void suspend_console(void)
printk("Suspending console(s) (use no_console_suspend to debug)\n");
acquire_console_sem();
console_suspended = 1;
+ up(&console_sem);
}
void resume_console(void)
{
if (!console_suspend_enabled)
return;
+ down(&console_sem);
console_suspended = 0;
release_console_sem();
}
@@ -912,11 +913,9 @@ void resume_console(void)
void acquire_console_sem(void)
{
BUG_ON(in_interrupt());
- if (console_suspended) {
- down(&secondary_console_sem);
- return;
- }
down(&console_sem);
+ if (console_suspended)
+ return;
console_locked = 1;
console_may_schedule = 1;
}
@@ -926,6 +925,10 @@ int try_acquire_console_sem(void)
{
if (down_trylock(&console_sem))
return -1;
+ if (console_suspended) {
+ up(&console_sem);
+ return -1;
+ }
console_locked = 1;
console_may_schedule = 0;
return 0;
@@ -979,7 +982,7 @@ void release_console_sem(void)
unsigned wake_klogd = 0;
if (console_suspended) {
- up(&secondary_console_sem);
+ up(&console_sem);
return;
}
diff --git a/kernel/sched.c b/kernel/sched.c
index 61245b8d0f16..7d97ff7c4478 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -6939,20 +6939,26 @@ static void free_rootdomain(struct root_domain *rd)
static void rq_attach_root(struct rq *rq, struct root_domain *rd)
{
+ struct root_domain *old_rd = NULL;
unsigned long flags;
spin_lock_irqsave(&rq->lock, flags);
if (rq->rd) {
- struct root_domain *old_rd = rq->rd;
+ old_rd = rq->rd;
if (cpumask_test_cpu(rq->cpu, old_rd->online))
set_rq_offline(rq);
cpumask_clear_cpu(rq->cpu, old_rd->span);
- if (atomic_dec_and_test(&old_rd->refcount))
- free_rootdomain(old_rd);
+ /*
+ * If we dont want to free the old_rt yet then
+ * set old_rd to NULL to skip the freeing later
+ * in this function:
+ */
+ if (!atomic_dec_and_test(&old_rd->refcount))
+ old_rd = NULL;
}
atomic_inc(&rd->refcount);
@@ -6963,6 +6969,9 @@ static void rq_attach_root(struct rq *rq, struct root_domain *rd)
set_rq_online(rq);
spin_unlock_irqrestore(&rq->lock, flags);
+
+ if (old_rd)
+ free_rootdomain(old_rd);
}
static int __init_refok init_rootdomain(struct root_domain *rd, bool bootmem)
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index e2a4ff6fc3a6..34e707e5ab87 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -52,6 +52,7 @@ config FUNCTION_TRACER
depends on HAVE_FUNCTION_TRACER
depends on DEBUG_KERNEL
select FRAME_POINTER
+ select KALLSYMS
select TRACING
select CONTEXT_SWITCH_TRACER
help
@@ -238,6 +239,7 @@ config STACK_TRACER
depends on DEBUG_KERNEL
select FUNCTION_TRACER
select STACKTRACE
+ select KALLSYMS
help
This special tracer records the maximum stack footprint of the
kernel and displays it in debugfs/tracing/stack_trace.
@@ -302,4 +304,27 @@ config FTRACE_STARTUP_TEST
functioning properly. It will do tests on all the configured
tracers of ftrace.
+config MMIOTRACE
+ bool "Memory mapped IO tracing"
+ depends on HAVE_MMIOTRACE_SUPPORT && DEBUG_KERNEL && PCI
+ select TRACING
+ help
+ Mmiotrace traces Memory Mapped I/O access and is meant for
+ debugging and reverse engineering. It is called from the ioremap
+ implementation and works via page faults. Tracing is disabled by
+ default and can be enabled at run-time.
+
+ See Documentation/tracers/mmiotrace.txt.
+ If you are not helping to develop drivers, say N.
+
+config MMIOTRACE_TEST
+ tristate "Test module for mmiotrace"
+ depends on MMIOTRACE && m
+ help
+ This is a dumb module for testing mmiotrace. It is very dangerous
+ as it will write garbage to IO memory starting at a given address.
+ However, it should be safe to use on e.g. unused portion of VRAM.
+
+ Say N, unless you absolutely know what you are doing.
+
endmenu
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 9a236ffe2aa4..fdf913dfc7e8 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -2033,7 +2033,7 @@ free:
static int start_graph_tracing(void)
{
struct ftrace_ret_stack **ret_stack_list;
- int ret;
+ int ret, cpu;
ret_stack_list = kmalloc(FTRACE_RETSTACK_ALLOC_SIZE *
sizeof(struct ftrace_ret_stack *),
@@ -2042,6 +2042,10 @@ static int start_graph_tracing(void)
if (!ret_stack_list)
return -ENOMEM;
+ /* The cpu_boot init_task->ret_stack will never be freed */
+ for_each_online_cpu(cpu)
+ ftrace_graph_init_task(idle_task(cpu));
+
do {
ret = alloc_retstack_tasklist(ret_stack_list);
} while (ret == -EAGAIN);
diff --git a/kernel/trace/trace_mmiotrace.c b/kernel/trace/trace_mmiotrace.c
index fffcb069f1dc..80e503ef6136 100644
--- a/kernel/trace/trace_mmiotrace.c
+++ b/kernel/trace/trace_mmiotrace.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/mmiotrace.h>
#include <linux/pci.h>
+#include <asm/atomic.h>
#include "trace.h"
@@ -19,6 +20,7 @@ struct header_iter {
static struct trace_array *mmio_trace_array;
static bool overrun_detected;
static unsigned long prev_overruns;
+static atomic_t dropped_count;
static void mmio_reset_data(struct trace_array *tr)
{
@@ -121,11 +123,11 @@ static void mmio_close(struct trace_iterator *iter)
static unsigned long count_overruns(struct trace_iterator *iter)
{
- unsigned long cnt = 0;
+ unsigned long cnt = atomic_xchg(&dropped_count, 0);
unsigned long over = ring_buffer_overruns(iter->tr->buffer);
if (over > prev_overruns)
- cnt = over - prev_overruns;
+ cnt += over - prev_overruns;
prev_overruns = over;
return cnt;
}
@@ -310,8 +312,10 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
&irq_flags);
- if (!event)
+ if (!event) {
+ atomic_inc(&dropped_count);
return;
+ }
entry = ring_buffer_event_data(event);
tracing_generic_entry_update(&entry->ent, 0, preempt_count());
entry->ent.type = TRACE_MMIO_RW;
@@ -338,8 +342,10 @@ static void __trace_mmiotrace_map(struct trace_array *tr,
event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry),
&irq_flags);
- if (!event)
+ if (!event) {
+ atomic_inc(&dropped_count);
return;
+ }
entry = ring_buffer_event_data(event);
tracing_generic_entry_update(&entry->ent, 0, preempt_count());
entry->ent.type = TRACE_MMIO_MAP;
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 88c8eb70f54a..bc8e80a86bca 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -23,10 +23,20 @@ static int trace_test_buffer_cpu(struct trace_array *tr, int cpu)
{
struct ring_buffer_event *event;
struct trace_entry *entry;
+ unsigned int loops = 0;
while ((event = ring_buffer_consume(tr->buffer, cpu, NULL))) {
entry = ring_buffer_event_data(event);
+ /*
+ * The ring buffer is a size of trace_buf_size, if
+ * we loop more than the size, there's something wrong
+ * with the ring buffer.
+ */
+ if (loops++ > trace_buf_size) {
+ printk(KERN_CONT ".. bad ring buffer ");
+ goto failed;
+ }
if (!trace_valid_entry(entry)) {
printk(KERN_CONT ".. invalid entry %d ",
entry->type);
@@ -57,11 +67,20 @@ static int trace_test_buffer(struct trace_array *tr, unsigned long *count)
cnt = ring_buffer_entries(tr->buffer);
+ /*
+ * The trace_test_buffer_cpu runs a while loop to consume all data.
+ * If the calling tracer is broken, and is constantly filling
+ * the buffer, this will run forever, and hard lock the box.
+ * We disable the ring buffer while we do this test to prevent
+ * a hard lock up.
+ */
+ tracing_off();
for_each_possible_cpu(cpu) {
ret = trace_test_buffer_cpu(tr, cpu);
if (ret)
break;
}
+ tracing_on();
__raw_spin_unlock(&ftrace_max_lock);
local_irq_restore(flags);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 29044f500269..1bcf9cd4baa0 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -838,7 +838,7 @@ config FIREWIRE_OHCI_REMOTE_DMA
If unsure, say N.
-menuconfig BUILD_DOCSRC
+config BUILD_DOCSRC
bool "Build targets in Documentation/ tree"
depends on HEADERS_CHECK
help
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 3c84128596ba..74dc57c74349 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -240,7 +240,7 @@ void bdi_writeout_inc(struct backing_dev_info *bdi)
}
EXPORT_SYMBOL_GPL(bdi_writeout_inc);
-static inline void task_dirty_inc(struct task_struct *tsk)
+void task_dirty_inc(struct task_struct *tsk)
{
prop_inc_single(&vm_dirties, &tsk->dirties);
}
@@ -1230,6 +1230,7 @@ int __set_page_dirty_nobuffers(struct page *page)
__inc_zone_page_state(page, NR_FILE_DIRTY);
__inc_bdi_stat(mapping->backing_dev_info,
BDI_RECLAIMABLE);
+ task_dirty_inc(current);
task_io_account_write(PAGE_CACHE_SIZE);
}
radix_tree_tag_set(&mapping->page_tree,
@@ -1262,7 +1263,7 @@ EXPORT_SYMBOL(redirty_page_for_writepage);
* If the mapping doesn't provide a set_page_dirty a_op, then
* just fall through and assume that it wants buffer_heads.
*/
-static int __set_page_dirty(struct page *page)
+int set_page_dirty(struct page *page)
{
struct address_space *mapping = page_mapping(page);
@@ -1280,14 +1281,6 @@ static int __set_page_dirty(struct page *page)
}
return 0;
}
-
-int set_page_dirty(struct page *page)
-{
- int ret = __set_page_dirty(page);
- if (ret)
- task_dirty_inc(current);
- return ret;
-}
EXPORT_SYMBOL(set_page_dirty);
/*
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 5675b3073854..5c44ed49ca93 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2989,7 +2989,7 @@ static int __meminit next_active_region_index_in_nid(int index, int nid)
* was used and there are no special requirements, this is a convenient
* alternative
*/
-int __meminit early_pfn_to_nid(unsigned long pfn)
+int __meminit __early_pfn_to_nid(unsigned long pfn)
{
int i;
@@ -3000,10 +3000,33 @@ int __meminit early_pfn_to_nid(unsigned long pfn)
if (start_pfn <= pfn && pfn < end_pfn)
return early_node_map[i].nid;
}
+ /* This is a memory hole */
+ return -1;
+}
+#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+
+int __meminit early_pfn_to_nid(unsigned long pfn)
+{
+ int nid;
+ nid = __early_pfn_to_nid(pfn);
+ if (nid >= 0)
+ return nid;
+ /* just returns 0 */
return 0;
}
-#endif /* CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID */
+
+#ifdef CONFIG_NODES_SPAN_OTHER_NODES
+bool __meminit early_pfn_in_nid(unsigned long pfn, int node)
+{
+ int nid;
+
+ nid = __early_pfn_to_nid(pfn);
+ if (nid >= 0 && nid != node)
+ return false;
+ return true;
+}
+#endif
/* Basic iterator support to walk early_node_map[] */
#define for_each_active_range_index_in_nid(i, nid) \
diff --git a/mm/page_io.c b/mm/page_io.c
index dc6ce0afbded..3023c475e041 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -111,7 +111,7 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
goto out;
}
if (wbc->sync_mode == WB_SYNC_ALL)
- rw |= (1 << BIO_RW_SYNC);
+ rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
count_vm_event(PSWPOUT);
set_page_writeback(page);
unlock_page(page);
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 7e6304dfafab..312fafe0ab6e 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -635,7 +635,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
if (!bdev) {
if (bdev_p)
- *bdev_p = sis->bdev;
+ *bdev_p = bdget(sis->bdev->bd_dev);
spin_unlock(&swap_lock);
return i;
@@ -647,7 +647,7 @@ int swap_type_of(dev_t device, sector_t offset, struct block_device **bdev_p)
struct swap_extent, list);
if (se->start_block == offset) {
if (bdev_p)
- *bdev_p = sis->bdev;
+ *bdev_p = bdget(sis->bdev->bd_dev);
spin_unlock(&swap_lock);
bdput(bdev);
diff --git a/mm/util.c b/mm/util.c
index cb00b748ce47..37eaccdf3054 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -129,6 +129,26 @@ void *krealloc(const void *p, size_t new_size, gfp_t flags)
}
EXPORT_SYMBOL(krealloc);
+/**
+ * kzfree - like kfree but zero memory
+ * @p: object to free memory of
+ *
+ * The memory of the object @p points to is zeroed before freed.
+ * If @p is %NULL, kzfree() does nothing.
+ */
+void kzfree(const void *p)
+{
+ size_t ks;
+ void *mem = (void *)p;
+
+ if (unlikely(ZERO_OR_NULL_PTR(mem)))
+ return;
+ ks = ksize(mem);
+ memset(mem, 0, ks);
+ kfree(mem);
+}
+EXPORT_SYMBOL(kzfree);
+
/*
* strndup_user - duplicate an existing string from user space
* @s: The string to duplicate
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 75f49d312e8c..903cad46e796 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -1012,6 +1012,8 @@ void __init vmalloc_init(void)
void unmap_kernel_range(unsigned long addr, unsigned long size)
{
unsigned long end = addr + size;
+
+ flush_cache_vunmap(addr, end);
vunmap_page_range(addr, end);
flush_tlb_kernel_range(addr, end);
}
@@ -1106,6 +1108,14 @@ struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags,
}
EXPORT_SYMBOL_GPL(__get_vm_area);
+struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags,
+ unsigned long start, unsigned long end,
+ void *caller)
+{
+ return __get_vm_area_node(size, flags, start, end, -1, GFP_KERNEL,
+ caller);
+}
+
/**
* get_vm_area - reserve a contiguous kernel virtual area
* @size: size of the area
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 9a27c44aa327..6177e3bcd66b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2057,31 +2057,31 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
int pass, struct scan_control *sc)
{
struct zone *zone;
- unsigned long nr_to_scan, ret = 0;
- enum lru_list l;
+ unsigned long ret = 0;
for_each_zone(zone) {
+ enum lru_list l;
if (!populated_zone(zone))
continue;
-
if (zone_is_all_unreclaimable(zone) && prio != DEF_PRIORITY)
continue;
for_each_evictable_lru(l) {
+ enum zone_stat_item ls = NR_LRU_BASE + l;
+ unsigned long lru_pages = zone_page_state(zone, ls);
+
/* For pass = 0, we don't shrink the active list */
- if (pass == 0 &&
- (l == LRU_ACTIVE || l == LRU_ACTIVE_FILE))
+ if (pass == 0 && (l == LRU_ACTIVE_ANON ||
+ l == LRU_ACTIVE_FILE))
continue;
- zone->lru[l].nr_scan +=
- (zone_page_state(zone, NR_LRU_BASE + l)
- >> prio) + 1;
+ zone->lru[l].nr_scan += (lru_pages >> prio) + 1;
if (zone->lru[l].nr_scan >= nr_pages || pass > 3) {
+ unsigned long nr_to_scan;
+
zone->lru[l].nr_scan = 0;
- nr_to_scan = min(nr_pages,
- zone_page_state(zone,
- NR_LRU_BASE + l));
+ nr_to_scan = min(nr_pages, lru_pages);
ret += shrink_list(l, nr_to_scan, zone,
sc, prio);
if (ret >= nr_pages)
@@ -2089,7 +2089,6 @@ static unsigned long shrink_all_zones(unsigned long nr_pages, int prio,
}
}
}
-
return ret;
}
@@ -2112,7 +2111,6 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
.may_swap = 0,
.swap_cluster_max = nr_pages,
.may_writepage = 1,
- .swappiness = vm_swappiness,
.isolate_pages = isolate_pages_global,
};
@@ -2146,10 +2144,8 @@ unsigned long shrink_all_memory(unsigned long nr_pages)
int prio;
/* Force reclaiming mapped pages in the passes #3 and #4 */
- if (pass > 2) {
+ if (pass > 2)
sc.may_swap = 1;
- sc.swappiness = 100;
- }
for (prio = DEF_PRIORITY; prio >= 0; prio--) {
unsigned long nr_to_scan = nr_pages - ret;
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 6bb2635b5ded..7bc992976d29 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -3,11 +3,16 @@
*
* This is an implementation of the CIPSO 2.2 protocol as specified in
* draft-ietf-cipso-ipsecurity-01.txt with additional tag types as found in
- * FIPS-188, copies of both documents can be found in the Documentation
- * directory. While CIPSO never became a full IETF RFC standard many vendors
+ * FIPS-188. While CIPSO never became a full IETF RFC standard many vendors
* have chosen to adopt the protocol and over the years it has become a
* de-facto standard for labeled networking.
*
+ * The CIPSO draft specification can be found in the kernel's Documentation
+ * directory as well as the following URL:
+ * http://netlabel.sourceforge.net/files/draft-ietf-cipso-ipsecurity-01.txt
+ * The FIPS-188 specification can be found at the following URL:
+ * http://www.itl.nist.gov/fipspubs/fip188.htm
+ *
* Author: Paul Moore <paul.moore@hp.com>
*
*/
diff --git a/scripts/bootgraph.pl b/scripts/bootgraph.pl
index b0246307aac4..12caa822a232 100644
--- a/scripts/bootgraph.pl
+++ b/scripts/bootgraph.pl
@@ -51,7 +51,7 @@ my %pidctr;
while (<>) {
my $line = $_;
- if ($line =~ /([0-9\.]+)\] calling ([a-zA-Z0-9\_]+)\+/) {
+ if ($line =~ /([0-9\.]+)\] calling ([a-zA-Z0-9\_\.]+)\+/) {
my $func = $2;
if ($done == 0) {
$start{$func} = $1;
@@ -87,7 +87,7 @@ while (<>) {
$count = $count + 1;
}
- if ($line =~ /([0-9\.]+)\] initcall ([a-zA-Z0-9\_]+)\+.*returned/) {
+ if ($line =~ /([0-9\.]+)\] initcall ([a-zA-Z0-9\_\.]+)\+.*returned/) {
if ($done == 0) {
$end{$2} = $1;
$maxtime = $1;
diff --git a/scripts/markup_oops.pl b/scripts/markup_oops.pl
index d40449cafa84..528492bcba5b 100644
--- a/scripts/markup_oops.pl
+++ b/scripts/markup_oops.pl
@@ -1,4 +1,4 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl
use File::Basename;
@@ -29,27 +29,151 @@ my $filename = $vmlinux_name;
my $target = "0";
my $function;
my $module = "";
-my $func_offset;
+my $func_offset = 0;
my $vmaoffset = 0;
+my %regs;
+
+
+sub parse_x86_regs
+{
+ my ($line) = @_;
+ if ($line =~ /EAX: ([0-9a-f]+) EBX: ([0-9a-f]+) ECX: ([0-9a-f]+) EDX: ([0-9a-f]+)/) {
+ $regs{"%eax"} = $1;
+ $regs{"%ebx"} = $2;
+ $regs{"%ecx"} = $3;
+ $regs{"%edx"} = $4;
+ }
+ if ($line =~ /ESI: ([0-9a-f]+) EDI: ([0-9a-f]+) EBP: ([0-9a-f]+) ESP: ([0-9a-f]+)/) {
+ $regs{"%esi"} = $1;
+ $regs{"%edi"} = $2;
+ $regs{"%esp"} = $4;
+ }
+ if ($line =~ /RAX: ([0-9a-f]+) RBX: ([0-9a-f]+) RCX: ([0-9a-f]+)/) {
+ $regs{"%eax"} = $1;
+ $regs{"%ebx"} = $2;
+ $regs{"%ecx"} = $3;
+ }
+ if ($line =~ /RDX: ([0-9a-f]+) RSI: ([0-9a-f]+) RDI: ([0-9a-f]+)/) {
+ $regs{"%edx"} = $1;
+ $regs{"%esi"} = $2;
+ $regs{"%edi"} = $3;
+ }
+ if ($line =~ /RBP: ([0-9a-f]+) R08: ([0-9a-f]+) R09: ([0-9a-f]+)/) {
+ $regs{"%r08"} = $2;
+ $regs{"%r09"} = $3;
+ }
+ if ($line =~ /R10: ([0-9a-f]+) R11: ([0-9a-f]+) R12: ([0-9a-f]+)/) {
+ $regs{"%r10"} = $1;
+ $regs{"%r11"} = $2;
+ $regs{"%r12"} = $3;
+ }
+ if ($line =~ /R13: ([0-9a-f]+) R14: ([0-9a-f]+) R15: ([0-9a-f]+)/) {
+ $regs{"%r13"} = $1;
+ $regs{"%r14"} = $2;
+ $regs{"%r15"} = $3;
+ }
+}
+
+sub reg_name
+{
+ my ($reg) = @_;
+ $reg =~ s/r(.)x/e\1x/;
+ $reg =~ s/r(.)i/e\1i/;
+ $reg =~ s/r(.)p/e\1p/;
+ return $reg;
+}
+
+sub process_x86_regs
+{
+ my ($line, $cntr) = @_;
+ my $str = "";
+ if (length($line) < 40) {
+ return ""; # not an asm istruction
+ }
+
+ # find the arguments to the instruction
+ if ($line =~ /([0-9a-zA-Z\,\%\(\)\-\+]+)$/) {
+ $lastword = $1;
+ } else {
+ return "";
+ }
+
+ # we need to find the registers that get clobbered,
+ # since their value is no longer relevant for previous
+ # instructions in the stream.
+
+ $clobber = $lastword;
+ # first, remove all memory operands, they're read only
+ $clobber =~ s/\([a-z0-9\%\,]+\)//g;
+ # then, remove everything before the comma, thats the read part
+ $clobber =~ s/.*\,//g;
+
+ # if this is the instruction that faulted, we haven't actually done
+ # the write yet... nothing is clobbered.
+ if ($cntr == 0) {
+ $clobber = "";
+ }
+
+ foreach $reg (keys(%regs)) {
+ my $clobberprime = reg_name($clobber);
+ my $lastwordprime = reg_name($lastword);
+ my $val = $regs{$reg};
+ if ($val =~ /^[0]+$/) {
+ $val = "0";
+ } else {
+ $val =~ s/^0*//;
+ }
+
+ # first check if we're clobbering this register; if we do
+ # we print it with a =>, and then delete its value
+ if ($clobber =~ /$reg/ || $clobberprime =~ /$reg/) {
+ if (length($val) > 0) {
+ $str = $str . " $reg => $val ";
+ }
+ $regs{$reg} = "";
+ $val = "";
+ }
+ # now check if we're reading this register
+ if ($lastword =~ /$reg/ || $lastwordprime =~ /$reg/) {
+ if (length($val) > 0) {
+ $str = $str . " $reg = $val ";
+ }
+ }
+ }
+ return $str;
+}
+
+# parse the oops
while (<STDIN>) {
my $line = $_;
if ($line =~ /EIP: 0060:\[\<([a-z0-9]+)\>\]/) {
$target = $1;
}
+ if ($line =~ /RIP: 0010:\[\<([a-z0-9]+)\>\]/) {
+ $target = $1;
+ }
if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]/) {
$function = $1;
$func_offset = $2;
}
+ if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\] \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]/) {
+ $function = $1;
+ $func_offset = $2;
+ }
# check if it's a module
if ($line =~ /EIP is at ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
$module = $3;
}
+ if ($line =~ /RIP: 0010:\[\<[0-9a-f]+\>\] \[\<[0-9a-f]+\>\] ([a-zA-Z0-9\_]+)\+(0x[0-9a-f]+)\/0x[a-f0-9]+\W\[([a-zA-Z0-9\_\-]+)\]/) {
+ $module = $3;
+ }
+ parse_x86_regs($line);
}
my $decodestart = hex($target) - hex($func_offset);
-my $decodestop = $decodestart + 8192;
+my $decodestop = hex($target) + 8192;
if ($target eq "0") {
print "No oops found!\n";
print "Usage: \n";
@@ -84,6 +208,7 @@ my $counter = 0;
my $state = 0;
my $center = 0;
my @lines;
+my @reglines;
sub InRange {
my ($address, $target) = @_;
@@ -188,16 +313,36 @@ while ($finish < $counter) {
my $i;
-my $fulltext = "";
+
+# start annotating the registers in the asm.
+# this goes from the oopsing point back, so that the annotator
+# can track (opportunistically) which registers got written and
+# whos value no longer is relevant.
+
+$i = $center;
+while ($i >= $start) {
+ $reglines[$i] = process_x86_regs($lines[$i], $center - $i);
+ $i = $i - 1;
+}
+
$i = $start;
while ($i < $finish) {
+ my $line;
if ($i == $center) {
- $fulltext = $fulltext . "*$lines[$i] <----- faulting instruction\n";
+ $line = "*$lines[$i] ";
} else {
- $fulltext = $fulltext . " $lines[$i]\n";
+ $line = " $lines[$i] ";
+ }
+ print $line;
+ if (defined($reglines[$i]) && length($reglines[$i]) > 0) {
+ my $c = 60 - length($line);
+ while ($c > 0) { print " "; $c = $c - 1; };
+ print "| $reglines[$i]";
}
+ if ($i == $center) {
+ print "<--- faulting instruction";
+ }
+ print "\n";
$i = $i +1;
}
-print $fulltext;
-
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 491b8b1b6abf..4eea60b1693e 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -210,6 +210,7 @@ static void do_usb_table(void *symval, unsigned long size,
static int do_hid_entry(const char *filename,
struct hid_device_id *id, char *alias)
{
+ id->bus = TO_NATIVE(id->bus);
id->vendor = TO_NATIVE(id->vendor);
id->product = TO_NATIVE(id->product);
diff --git a/scripts/package/mkspec b/scripts/package/mkspec
index 2500886fb90a..ee448cdc6a2b 100755
--- a/scripts/package/mkspec
+++ b/scripts/package/mkspec
@@ -86,6 +86,14 @@ echo "%endif"
echo 'cp System.map $RPM_BUILD_ROOT'"/boot/System.map-$KERNELRELEASE"
echo 'cp .config $RPM_BUILD_ROOT'"/boot/config-$KERNELRELEASE"
+
+echo "%ifnarch ppc64"
+echo 'cp vmlinux vmlinux.orig'
+echo 'bzip2 -9 vmlinux'
+echo 'mv vmlinux.bz2 $RPM_BUILD_ROOT'"/boot/vmlinux-$KERNELRELEASE.bz2"
+echo 'mv vmlinux.orig vmlinux'
+echo "%endif"
+
echo ""
echo "%clean"
echo '#echo -rf $RPM_BUILD_ROOT'
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index f6946cf99ce1..f1c4b35bc324 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -58,14 +58,7 @@ fi
# Check for svn and a svn repo.
if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then
rev=`echo $rev | awk '{print $NF}'`
- changes=`svn status 2>/dev/null | grep '^[AMD]' | wc -l`
-
- # Are there uncommitted changes?
- if [ $changes != 0 ]; then
- printf -- '-svn%s%s' "$rev" -dirty
- else
- printf -- '-svn%s' "$rev"
- fi
+ printf -- '-svn%s' "$rev"
# All done with svn
exit
diff --git a/scripts/tags.sh b/scripts/tags.sh
index fdbe78bb5e2b..5bd8b1003d44 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -76,7 +76,10 @@ all_sources()
all_kconfigs()
{
- find_sources $ALLSOURCE_ARCHS 'Kconfig*'
+ for arch in $ALLSOURCE_ARCHS; do
+ find_sources $arch 'Kconfig*'
+ done
+ find_other_sources 'Kconfig*'
}
all_defconfigs()
@@ -99,7 +102,8 @@ exuberant()
-I ____cacheline_internodealigned_in_smp \
-I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL \
--extra=+f --c-kinds=+px \
- --regex-asm='/^ENTRY\(([^)]*)\).*/\1/'
+ --regex-asm='/^ENTRY\(([^)]*)\).*/\1/' \
+ --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/'
all_kconfigs | xargs $1 -a \
--langdef=kconfig --language-force=kconfig \
@@ -117,7 +121,9 @@ exuberant()
emacs()
{
- all_sources | xargs $1 -a
+ all_sources | xargs $1 -a \
+ --regex='/^ENTRY(\([^)]*\)).*/\1/' \
+ --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/'
all_kconfigs | xargs $1 -a \
--regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/'
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c
index f58701a7b728..3f4b26647386 100644
--- a/security/selinux/netlabel.c
+++ b/security/selinux/netlabel.c
@@ -490,8 +490,10 @@ int selinux_netlbl_socket_setsockopt(struct socket *sock,
lock_sock(sk);
rc = netlbl_sock_getattr(sk, &secattr);
release_sock(sk);
- if (rc == 0 && secattr.flags != NETLBL_SECATTR_NONE)
+ if (rc == 0)
rc = -EACCES;
+ else if (rc == -ENOMSG)
+ rc = 0;
netlbl_secattr_destroy(&secattr);
}
diff --git a/sound/core/jack.c b/sound/core/jack.c
index dd4a12dc09aa..077a85262c1c 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -47,7 +47,7 @@ static int snd_jack_dev_register(struct snd_device *device)
int err;
snprintf(jack->name, sizeof(jack->name), "%s %s",
- card->longname, jack->id);
+ card->shortname, jack->id);
jack->input_dev->name = jack->name;
/* Default to the sound card device. */
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
index 57d9f154c88b..38931f2f6967 100644
--- a/sound/oss/dmasound/dmasound_atari.c
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -847,23 +847,23 @@ static int __init AtaIrqInit(void)
of events. So all we need to keep the music playing is
to provide the sound hardware with new data upon
an interrupt from timer A. */
- mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */
- mfp.tim_dt_a = 1; /* Cause interrupt after first event. */
- mfp.tim_ct_a = 8; /* Turn on event counting. */
+ st_mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */
+ st_mfp.tim_dt_a = 1; /* Cause interrupt after first event. */
+ st_mfp.tim_ct_a = 8; /* Turn on event counting. */
/* Register interrupt handler. */
if (request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound",
AtaInterrupt))
return 0;
- mfp.int_en_a |= 0x20; /* Turn interrupt on. */
- mfp.int_mk_a |= 0x20;
+ st_mfp.int_en_a |= 0x20; /* Turn interrupt on. */
+ st_mfp.int_mk_a |= 0x20;
return 1;
}
#ifdef MODULE
static void AtaIrqCleanUp(void)
{
- mfp.tim_ct_a = 0; /* stop timer */
- mfp.int_en_a &= ~0x20; /* turn interrupt off */
+ st_mfp.tim_ct_a = 0; /* stop timer */
+ st_mfp.int_en_a &= ~0x20; /* turn interrupt off */
free_irq(IRQ_MFP_TIMA, AtaInterrupt);
}
#endif /* MODULE */
@@ -1599,7 +1599,7 @@ static int __init dmasound_atari_init(void)
is_falcon = 0;
} else
return -ENODEV;
- if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
+ if ((st_mfp.int_en_a & st_mfp.int_mk_a & 0x20) == 0)
return dmasound_init();
else {
printk("DMA sound driver: Timer A interrupt already in use\n");
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 11e791b965f6..c8d9178f47e5 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1947,16 +1947,13 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
return 0;
}
-static int azx_resume_early(struct pci_dev *pci)
-{
- return pci_restore_state(pci);
-}
-
static int azx_resume(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
+ pci_set_power_state(pci, PCI_D0);
+ pci_restore_state(pci);
if (pci_enable_device(pci) < 0) {
printk(KERN_ERR "hda-intel: pci_enable_device failed, "
"disabling device\n");
@@ -2468,7 +2465,6 @@ static struct pci_driver driver = {
.remove = __devexit_p(azx_remove),
#ifdef CONFIG_PM
.suspend = azx_suspend,
- .resume_early = azx_resume_early,
.resume = azx_resume,
#endif
};
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 18c7c91786bc..6c870c12a177 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -26,7 +26,7 @@
* SPI 0 -> 1st PCM1796 (front)
* SPI 1 -> 2nd PCM1796 (surround)
* SPI 2 -> 3rd PCM1796 (center/LFE)
- * SPI 4 -> 4th PCM1796 (back) and EEPROM self-destruct (do not use!)
+ * SPI 4 -> 4th PCM1796 (back)
*
* GPIO 2 -> M0 of CS5381
* GPIO 3 -> M1 of CS5381
@@ -207,12 +207,6 @@ static void xonar_gpio_changed(struct oxygen *chip);
static inline void pcm1796_write_spi(struct oxygen *chip, unsigned int codec,
u8 reg, u8 value)
{
- /*
- * We don't want to do writes on SPI 4 because the EEPROM, which shares
- * the same pin, might get confused and broken. We'd better take care
- * that the driver works with the default register values ...
- */
-#if 0
/* maps ALSA channel pair number to SPI output */
static const u8 codec_map[4] = {
0, 1, 2, 4
@@ -223,7 +217,6 @@ static inline void pcm1796_write_spi(struct oxygen *chip, unsigned int codec,
(codec_map[codec] << OXYGEN_SPI_CODEC_SHIFT) |
OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
(reg << 8) | value);
-#endif
}
static inline void pcm1796_write_i2c(struct oxygen *chip, unsigned int codec,
@@ -757,9 +750,6 @@ static const DECLARE_TLV_DB_SCALE(cs4362a_db_scale, -12700, 100, 0);
static int xonar_d2_control_filter(struct snd_kcontrol_new *template)
{
- if (!strncmp(template->name, "Master Playback ", 16))
- /* disable volume/mute because they would require SPI writes */
- return 1;
if (!strncmp(template->name, "CD Capture ", 11))
/* CD in is actually connected to the video in pin */
template->private_value ^= AC97_CD ^ AC97_VIDEO;
@@ -850,8 +840,9 @@ static const struct oxygen_model model_xonar_d2 = {
.dac_volume_min = 0x0f,
.dac_volume_max = 0xff,
.misc_flags = OXYGEN_MISC_MIDI,
- .function_flags = OXYGEN_FUNCTION_SPI,
- .dac_i2s_format = OXYGEN_I2S_FORMAT_I2S,
+ .function_flags = OXYGEN_FUNCTION_SPI |
+ OXYGEN_FUNCTION_ENABLE_SPI_4_5,
+ .dac_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
.adc_i2s_format = OXYGEN_I2S_FORMAT_LJUST,
};
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 2ab83129d9b0..19e37451c216 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -2524,7 +2524,6 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
* build the rate table and bitmap flags
*/
int r, idx;
- unsigned int nonzero_rates = 0;
fp->rate_table = kmalloc(sizeof(int) * nr_rates, GFP_KERNEL);
if (fp->rate_table == NULL) {
@@ -2532,24 +2531,27 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
return -1;
}
- fp->nr_rates = nr_rates;
- fp->rate_min = fp->rate_max = combine_triple(&fmt[8]);
+ fp->nr_rates = 0;
+ fp->rate_min = fp->rate_max = 0;
for (r = 0, idx = offset + 1; r < nr_rates; r++, idx += 3) {
unsigned int rate = combine_triple(&fmt[idx]);
+ if (!rate)
+ continue;
/* C-Media CM6501 mislabels its 96 kHz altsetting */
if (rate == 48000 && nr_rates == 1 &&
- chip->usb_id == USB_ID(0x0d8c, 0x0201) &&
+ (chip->usb_id == USB_ID(0x0d8c, 0x0201) ||
+ chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
fp->altsetting == 5 && fp->maxpacksize == 392)
rate = 96000;
- fp->rate_table[r] = rate;
- nonzero_rates |= rate;
- if (rate < fp->rate_min)
+ fp->rate_table[fp->nr_rates] = rate;
+ if (!fp->rate_min || rate < fp->rate_min)
fp->rate_min = rate;
- else if (rate > fp->rate_max)
+ if (!fp->rate_max || rate > fp->rate_max)
fp->rate_max = rate;
fp->rates |= snd_pcm_rate_to_rate_bit(rate);
+ fp->nr_rates++;
}
- if (!nonzero_rates) {
+ if (!fp->nr_rates) {
hwc_debug("All rates were zero. Skipping format!\n");
return -1;
}
diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 320641ab5be7..26bad373fe65 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1625,6 +1625,7 @@ static int snd_usbmidi_create_endpoints_midiman(struct snd_usb_midi* umidi,
}
ep_info.out_ep = get_endpoint(hostif, 2)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ ep_info.out_interval = 0;
ep_info.out_cables = endpoint->out_cables & 0x5555;
err = snd_usbmidi_out_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
if (err < 0)
diff --git a/virt/kvm/iommu.c b/virt/kvm/iommu.c
index e9693a29d00e..4c4037503600 100644
--- a/virt/kvm/iommu.c
+++ b/virt/kvm/iommu.c
@@ -73,14 +73,13 @@ static int kvm_iommu_map_memslots(struct kvm *kvm)
{
int i, r = 0;
- down_read(&kvm->slots_lock);
for (i = 0; i < kvm->nmemslots; i++) {
r = kvm_iommu_map_pages(kvm, kvm->memslots[i].base_gfn,
kvm->memslots[i].npages);
if (r)
break;
}
- up_read(&kvm->slots_lock);
+
return r;
}
@@ -190,12 +189,11 @@ static void kvm_iommu_put_pages(struct kvm *kvm,
static int kvm_iommu_unmap_memslots(struct kvm *kvm)
{
int i;
- down_read(&kvm->slots_lock);
+
for (i = 0; i < kvm->nmemslots; i++) {
kvm_iommu_put_pages(kvm, kvm->memslots[i].base_gfn,
kvm->memslots[i].npages);
}
- up_read(&kvm->slots_lock);
return 0;
}
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 3a5a08298aab..29a667ce35b0 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -173,7 +173,6 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
assigned_dev->host_irq_disabled = false;
}
mutex_unlock(&assigned_dev->kvm->lock);
- kvm_put_kvm(assigned_dev->kvm);
}
static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
@@ -181,8 +180,6 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
struct kvm_assigned_dev_kernel *assigned_dev =
(struct kvm_assigned_dev_kernel *) dev_id;
- kvm_get_kvm(assigned_dev->kvm);
-
schedule_work(&assigned_dev->interrupt_work);
disable_irq_nosync(irq);
@@ -213,6 +210,7 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
}
}
+/* The function implicit hold kvm->lock mutex due to cancel_work_sync() */
static void kvm_free_assigned_irq(struct kvm *kvm,
struct kvm_assigned_dev_kernel *assigned_dev)
{
@@ -228,11 +226,24 @@ static void kvm_free_assigned_irq(struct kvm *kvm,
if (!assigned_dev->irq_requested_type)
return;
- if (cancel_work_sync(&assigned_dev->interrupt_work))
- /* We had pending work. That means we will have to take
- * care of kvm_put_kvm.
- */
- kvm_put_kvm(kvm);
+ /*
+ * In kvm_free_device_irq, cancel_work_sync return true if:
+ * 1. work is scheduled, and then cancelled.
+ * 2. work callback is executed.
+ *
+ * The first one ensured that the irq is disabled and no more events
+ * would happen. But for the second one, the irq may be enabled (e.g.
+ * for MSI). So we disable irq here to prevent further events.
+ *
+ * Notice this maybe result in nested disable if the interrupt type is
+ * INTx, but it's OK for we are going to free it.
+ *
+ * If this function is a part of VM destroy, please ensure that till
+ * now, the kvm state is still legal for probably we also have to wait
+ * interrupt_work done.
+ */
+ disable_irq_nosync(assigned_dev->host_irq);
+ cancel_work_sync(&assigned_dev->interrupt_work);
free_irq(assigned_dev->host_irq, (void *)assigned_dev);
@@ -285,8 +296,8 @@ static int assigned_device_update_intx(struct kvm *kvm,
if (irqchip_in_kernel(kvm)) {
if (!msi2intx &&
- adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) {
- free_irq(adev->host_irq, (void *)kvm);
+ (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)) {
+ free_irq(adev->host_irq, (void *)adev);
pci_disable_msi(adev->dev);
}
@@ -455,6 +466,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
struct kvm_assigned_dev_kernel *match;
struct pci_dev *dev;
+ down_read(&kvm->slots_lock);
mutex_lock(&kvm->lock);
match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
@@ -516,6 +528,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
out:
mutex_unlock(&kvm->lock);
+ up_read(&kvm->slots_lock);
return r;
out_list_del:
list_del(&match->list);
@@ -527,6 +540,7 @@ out_put:
out_free:
kfree(match);
mutex_unlock(&kvm->lock);
+ up_read(&kvm->slots_lock);
return r;
}
#endif
@@ -789,11 +803,19 @@ static int kvm_mmu_notifier_clear_flush_young(struct mmu_notifier *mn,
return young;
}
+static void kvm_mmu_notifier_release(struct mmu_notifier *mn,
+ struct mm_struct *mm)
+{
+ struct kvm *kvm = mmu_notifier_to_kvm(mn);
+ kvm_arch_flush_shadow(kvm);
+}
+
static const struct mmu_notifier_ops kvm_mmu_notifier_ops = {
.invalidate_page = kvm_mmu_notifier_invalidate_page,
.invalidate_range_start = kvm_mmu_notifier_invalidate_range_start,
.invalidate_range_end = kvm_mmu_notifier_invalidate_range_end,
.clear_flush_young = kvm_mmu_notifier_clear_flush_young,
+ .release = kvm_mmu_notifier_release,
};
#endif /* CONFIG_MMU_NOTIFIER && KVM_ARCH_WANT_MMU_NOTIFIER */
@@ -883,6 +905,7 @@ static void kvm_destroy_vm(struct kvm *kvm)
{
struct mm_struct *mm = kvm->mm;
+ kvm_arch_sync_events(kvm);
spin_lock(&kvm_lock);
list_del(&kvm->vm_list);
spin_unlock(&kvm_lock);